diff --git a/.github/workflows/buildx.yaml b/.github/workflows/buildx.yaml index 7a8d1c0..0ea67d2 100644 --- a/.github/workflows/buildx.yaml +++ b/.github/workflows/buildx.yaml @@ -4,7 +4,7 @@ name: Docker on: [push] jobs: build: - runs-on: ubuntu-18.04 + runs-on: ubuntu-latest steps: - name: Prepare id: prepare @@ -19,7 +19,7 @@ jobs: echo ::set-output name=version::snapshot fi - echo ::set-output name=docker_platforms::linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64/v8,linux/386 + echo ::set-output name=docker_platforms::linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64/v8,linux/386,linux/s390x echo ::set-output name=docker_image::${{ secrets.DOCKER_USERNAME }}/${{ github.event.repository.name }} # https://github.com/crazy-max/ghaction-docker-buildx diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..e5e3f10 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,38 @@ +name: goreleaser + +on: + push: + # run only against tags + tags: + - 'v*' + +permissions: + contents: write + # packages: write + # issues: write + +jobs: + goreleaser: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + - run: git fetch --force --tags + - uses: actions/setup-go@v3 + with: + go-version: '1.19' + cache: true + # More assembly might be required: Docker logins, GPG, etc. It all depends + # on your needs. + - uses: goreleaser/goreleaser-action@v4 + with: + # either 'goreleaser' (default) or 'goreleaser-pro': + distribution: goreleaser + version: latest + args: release --clean + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # Your GoReleaser Pro key, if you are using the 'goreleaser-pro' + # distribution: + # GORELEASER_KEY: ${{ secrets.GORELEASER_KEY }} diff --git a/.gitignore b/.gitignore index 0cd5cca..2016845 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,7 @@ _test release debian bin +dist/ # Architecture specific extensions/prefixes *.[568vq] @@ -30,5 +31,5 @@ _testmain.go *.bak +.vscode/ cmd/gost/gost -snap diff --git a/.goreleaser.yaml b/.goreleaser.yaml new file mode 100644 index 0000000..63dd2eb --- /dev/null +++ b/.goreleaser.yaml @@ -0,0 +1,58 @@ +# This is an example .goreleaser.yml file with some sensible defaults. +# Make sure to check the documentation at https://goreleaser.com +before: + hooks: + # You may remove this if you don't use go modules. + - go mod tidy + # you may remove this if you don't need go generate + # - go generate ./... +builds: + - env: + - CGO_ENABLED=0 + main: ./cmd/gost + targets: + - darwin_amd64 + - darwin_arm64 + - linux_386 + - linux_amd64 + - linux_amd64_v3 + - linux_arm_5 + - linux_arm_6 + - linux_arm_7 + - linux_arm64 + - linux_mips_softfloat + - linux_mips_hardfloat + - linux_mipsle_softfloat + - linux_mipsle_hardfloat + - linux_mips64 + - linux_mips64le + - linux_s390x + - linux_riscv64 + - freebsd_386 + - freebsd_amd64 + - windows_386 + - windows_amd64 + - windows_amd64_v3 + - windows_arm64 + +archives: + - format: tar.gz + # use zip for windows archives + format_overrides: + - goos: windows + format: zip +checksum: + name_template: 'checksums.txt' +snapshot: + name_template: "{{ incpatch .Version }}-next" +changelog: + sort: asc + filters: + exclude: + - '^docs:' + - '^test:' + +# The lines beneath this are called `modelines`. See `:help modeline` +# Feel free to remove those if you don't want/use them. +# yaml-language-server: $schema=https://goreleaser.com/static/schema.json +# vim: set ts=2 sw=2 tw=0 fo=cnqoj diff --git a/Dockerfile b/Dockerfile index ec2b791..6186a99 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM --platform=$BUILDPLATFORM golang:1-alpine as builder +FROM --platform=$BUILDPLATFORM golang:1.20-alpine as builder # Convert TARGETPLATFORM to GOARCH format # https://github.com/tonistiigi/xx diff --git a/Makefile b/Makefile index f3721b7..712e9ff 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ NAME=gost BINDIR=bin VERSION=$(shell cat gost.go | grep 'Version =' | sed 's/.*\"\(.*\)\".*/\1/g') GOBUILD=CGO_ENABLED=0 go build --ldflags="-s -w" -v -x -a -GOFILES=cmd/gost/* +GOFILES=cmd/gost/*.go PLATFORM_LIST = \ darwin-amd64 \ @@ -19,12 +19,15 @@ PLATFORM_LIST = \ linux-mipsle-hardfloat \ linux-mips64 \ linux-mips64le \ + linux-s390x \ + linux-riscv64 \ freebsd-386 \ freebsd-amd64 WINDOWS_ARCH_LIST = \ windows-386 \ - windows-amd64 + windows-amd64 \ + windows-arm64 all: linux-amd64 darwin-amd64 windows-amd64 # Most used @@ -70,6 +73,12 @@ linux-mips64: linux-mips64le: GOARCH=mips64le GOOS=linux $(GOBUILD) -o $(BINDIR)/$(NAME)-$@ $(GOFILES) +linux-s390x: + GOARCH=s390x GOOS=linux $(GOBUILD) -o $(BINDIR)/$(NAME)-$@ $(GOFILES) + +linux-riscv64: + GOARCH=riscv64 GOOS=linux $(GOBUILD) -o $(BINDIR)/$(NAME)-$@ $(GOFILES) + freebsd-386: GOARCH=386 GOOS=freebsd $(GOBUILD) -o $(BINDIR)/$(NAME)-$@ $(GOFILES) @@ -82,6 +91,9 @@ windows-386: windows-amd64: GOARCH=amd64 GOOS=windows $(GOBUILD) -o $(BINDIR)/$(NAME)-$@.exe $(GOFILES) +windows-arm64: + GOARCH=arm64 GOOS=windows $(GOBUILD) -o $(BINDIR)/$(NAME)-$@.exe $(GOFILES) + gz_releases=$(addsuffix .gz, $(PLATFORM_LIST)) zip_releases=$(addsuffix .zip, $(WINDOWS_ARCH_LIST)) diff --git a/README.md b/README.md index d9ed8fd..f41aa36 100644 --- a/README.md +++ b/README.md @@ -1,39 +1,40 @@ -gost - GO Simple Tunnel +GO Simple Tunnel ====== ### GO语言实现的安全隧道 [![GoDoc](https://godoc.org/github.com/ginuerzh/gost?status.svg)](https://godoc.org/github.com/ginuerzh/gost) -[![Build Status](https://travis-ci.org/ginuerzh/gost.svg?branch=master)](https://travis-ci.org/ginuerzh/gost) [![Go Report Card](https://goreportcard.com/badge/github.com/ginuerzh/gost)](https://goreportcard.com/report/github.com/ginuerzh/gost) [![codecov](https://codecov.io/gh/ginuerzh/gost/branch/master/graphs/badge.svg)](https://codecov.io/gh/ginuerzh/gost/branch/master) [![GitHub release](https://img.shields.io/github/release/ginuerzh/gost.svg)](https://github.com/ginuerzh/gost/releases/latest) -[![Snap Status](https://build.snapcraft.io/badge/ginuerzh/gost.svg)](https://build.snapcraft.io/user/ginuerzh/gost) -[![Docker Build Status](https://img.shields.io/docker/build/ginuerzh/gost.svg)](https://hub.docker.com/r/ginuerzh/gost/) +[![Docker](https://img.shields.io/docker/pulls/ginuerzh/gost.svg)](https://hub.docker.com/r/ginuerzh/gost/) +[![gost](https://snapcraft.io/gost/badge.svg)](https://snapcraft.io/gost) [English README](README_en.md) +### !!![V3版本已经可用,欢迎抢先体验](https://latest.gost.run)!!! + 特性 ------ * 多端口监听 * 可设置转发代理,支持多级转发(代理链) * 支持标准HTTP/HTTPS/HTTP2/SOCKS4(A)/SOCKS5代理协议 -* Web代理支持[探测防御](https://docs.ginuerzh.xyz/gost/probe_resist/) -* [支持多种隧道类型](https://docs.ginuerzh.xyz/gost/configuration/) -* [SOCKS5代理支持TLS协商加密](https://docs.ginuerzh.xyz/gost/socks/) -* [Tunnel UDP over TCP](https://docs.ginuerzh.xyz/gost/socks/) -* [TCP/UDP透明代理](https://docs.ginuerzh.xyz/gost/redirect/) -* [本地/远程TCP/UDP端口转发](https://docs.ginuerzh.xyz/gost/port-forwarding/) -* [支持Shadowsocks(TCP/UDP)协议](https://docs.ginuerzh.xyz/gost/ss/) -* [支持SNI代理](https://docs.ginuerzh.xyz/gost/sni/) -* [权限控制](https://docs.ginuerzh.xyz/gost/permission/) -* [负载均衡](https://docs.ginuerzh.xyz/gost/load-balancing/) -* [路由控制](https://docs.ginuerzh.xyz/gost/bypass/) -* DNS[解析](https://docs.ginuerzh.xyz/gost/resolver/)和[代理](https://docs.ginuerzh.xyz/gost/dns/) -* [TUN/TAP设备](https://docs.ginuerzh.xyz/gost/tuntap/) +* Web代理支持[探测防御](https://v2.gost.run/probe_resist/) +* [支持多种隧道类型](https://v2.gost.run/configuration/) +* [SOCKS5代理支持TLS协商加密](https://v2.gost.run/socks/) +* [Tunnel UDP over TCP](https://v2.gost.run/socks/) +* [TCP/UDP透明代理](https://v2.gost.run/redirect/) +* [本地/远程TCP/UDP端口转发](https://v2.gost.run/port-forwarding/) +* [支持Shadowsocks(TCP/UDP)协议](https://v2.gost.run/ss/) +* [支持SNI代理](https://v2.gost.run/sni/) +* [权限控制](https://v2.gost.run/permission/) +* [负载均衡](https://v2.gost.run/load-balancing/) +* [路由控制](https://v2.gost.run/bypass/) +* DNS[解析](https://v2.gost.run/resolver/)和[代理](https://v2.gost.run/dns/) +* [TUN/TAP设备](https://v2.gost.run/tuntap/) -Wiki站点: +Wiki站点: [v2.gost.run](https://v2.gost.run) Telegram讨论群: @@ -57,7 +58,7 @@ go build #### Docker ```bash -docker pull ginuerzh/gost +docker run --rm ginuerzh/gost -V ``` #### Homebrew @@ -68,6 +69,7 @@ brew install gost #### Ubuntu商店 + ```bash sudo snap install core sudo snap install gost @@ -193,7 +195,7 @@ gost -L=:8080 -F=h2://server_ip:443 ``` #### QUIC -gost对QUIC的支持是基于[quic-go](https://github.com/lucas-clemente/quic-go)库。 +gost对QUIC的支持是基于[quic-go](https://github.com/quic-go/quic-go)库。 服务端: ```bash diff --git a/README_en.md b/README_en.md index 34c9c86..fbeb7bf 100644 --- a/README_en.md +++ b/README_en.md @@ -4,33 +4,32 @@ gost - GO Simple Tunnel ### A simple security tunnel written in Golang [![GoDoc](https://godoc.org/github.com/ginuerzh/gost?status.svg)](https://godoc.org/github.com/ginuerzh/gost) -[![Build Status](https://travis-ci.org/ginuerzh/gost.svg?branch=master)](https://travis-ci.org/ginuerzh/gost) [![Go Report Card](https://goreportcard.com/badge/github.com/ginuerzh/gost)](https://goreportcard.com/report/github.com/ginuerzh/gost) [![codecov](https://codecov.io/gh/ginuerzh/gost/branch/master/graphs/badge.svg)](https://codecov.io/gh/ginuerzh/gost/branch/master) [![GitHub release](https://img.shields.io/github/release/ginuerzh/gost.svg)](https://github.com/ginuerzh/gost/releases/latest) -[![Snap Status](https://build.snapcraft.io/badge/ginuerzh/gost.svg)](https://build.snapcraft.io/user/ginuerzh/gost) -[![Docker Build Status](https://img.shields.io/docker/build/ginuerzh/gost.svg)](https://hub.docker.com/r/ginuerzh/gost/) - +[![Docker](https://img.shields.io/docker/pulls/ginuerzh/gost.svg)](https://hub.docker.com/r/ginuerzh/gost/) +[![gost](https://snapcraft.io/gost/badge.svg)](https://snapcraft.io/gost) + Features ------ * Listening on multiple ports * Multi-level forward proxy - proxy chain * Standard HTTP/HTTPS/HTTP2/SOCKS4(A)/SOCKS5 proxy protocols support -* [Probing resistance](https://docs.ginuerzh.xyz/gost/en/probe_resist/) support for web proxy -* [Support multiple tunnel types](https://docs.ginuerzh.xyz/gost/en/configuration/) -* [TLS encryption via negotiation support for SOCKS5 proxy](https://docs.ginuerzh.xyz/gost/en/socks/) -* [Tunnel UDP over TCP](https://docs.ginuerzh.xyz/gost/en/socks/) -* [TCP/UDP Transparent proxy](https://docs.ginuerzh.xyz/gost/en/redirect/) -* [Local/remote TCP/UDP port forwarding](https://docs.ginuerzh.xyz/gost/en/port-forwarding/) -* [Shadowsocks protocol](https://docs.ginuerzh.xyz/gost/en/ss/) -* [SNI proxy](https://docs.ginuerzh.xyz/gost/en/sni/) -* [Permission control](https://docs.ginuerzh.xyz/gost/en/permission/) -* [Load balancing](https://docs.ginuerzh.xyz/gost/en/load-balancing/) -* [Routing control](https://docs.ginuerzh.xyz/gost/en/bypass/) -* DNS [resolver](https://docs.ginuerzh.xyz/gost/resolver/) and [proxy](https://docs.ginuerzh.xyz/gost/dns/) -* [TUN/TAP device](https://docs.ginuerzh.xyz/gost/en/tuntap/) +* [Probing resistance](https://v2.gost.run/en/probe_resist/) support for web proxy +* [Support multiple tunnel types](https://v2.gost.run/en/configuration/) +* [TLS encryption via negotiation support for SOCKS5 proxy](https://v2.gost.run/en/socks/) +* [Tunnel UDP over TCP](https://v2.gost.run/en/socks/) +* [TCP/UDP Transparent proxy](https://v2.gost.run/en/redirect/) +* [Local/remote TCP/UDP port forwarding](https://v2.gost.run/en/port-forwarding/) +* [Shadowsocks protocol](https://v2.gost.run/en/ss/) +* [SNI proxy](https://v2.gost.run/en/sni/) +* [Permission control](https://v2.gost.run/en/permission/) +* [Load balancing](https://v2.gost.run/en/load-balancing/) +* [Routing control](https://v2.gost.run/en/bypass/) +* DNS [resolver](https://v2.gost.run/resolver/) and [proxy](https://v2.gost.run/dns/) +* [TUN/TAP device](https://v2.gost.run/en/tuntap/) -Wiki: +Wiki: [v2.gost.run](https://v2.gost.run/en/) Telegram group: @@ -54,7 +53,7 @@ go build #### Docker ```bash -docker pull ginuerzh/gost +docker run --rm ginuerzh/gost -V ``` #### Homebrew @@ -219,7 +218,7 @@ gost -L=:8080 -F=h2://server_ip:443 #### QUIC -Support for QUIC is based on library [quic-go](https://github.com/lucas-clemente/quic-go). +Support for QUIC is based on library [quic-go](https://github.com/quic-go/quic-go). Server: diff --git a/chain.go b/chain.go index bedeb6f..8d3bc6f 100644 --- a/chain.go +++ b/chain.go @@ -3,7 +3,9 @@ package gost import ( "context" "errors" + "fmt" "net" + "syscall" "time" "github.com/go-log/log" @@ -18,6 +20,8 @@ var ( type Chain struct { isRoute bool Retries int + Mark int + Interface string nodeGroups []*NodeGroup route []Node // nodes in the selected route } @@ -34,10 +38,14 @@ func NewChain(nodes ...Node) *Chain { // newRoute creates a chain route. // a chain route is the final route after node selection. -func newRoute(nodes ...Node) *Chain { - chain := NewChain(nodes...) - chain.isRoute = true - return chain +func (c *Chain) newRoute(nodes ...Node) *Chain { + route := NewChain(nodes...) + route.isRoute = true + if !c.IsEmpty() { + route.Interface = c.Interface + route.Mark = c.Mark + } + return route } // Nodes returns the proxy nodes that the chain holds. @@ -135,6 +143,9 @@ func (c *Chain) dialWithOptions(ctx context.Context, network, address string, op if options == nil { options = &ChainOptions{} } + if c == nil { + c = &Chain{} + } route, err := c.selectRouteFor(address) if err != nil { return nil, err @@ -143,6 +154,9 @@ func (c *Chain) dialWithOptions(ctx context.Context, network, address string, op ipAddr := address if address != "" { ipAddr = c.resolve(address, options.Resolver, options.Hosts) + if ipAddr == "" { + return nil, fmt.Errorf("resolver: domain %s does not exists", address) + } } timeout := options.Timeout @@ -150,6 +164,32 @@ func (c *Chain) dialWithOptions(ctx context.Context, network, address string, op timeout = DialTimeout } + var controlFunction func(_ string, _ string, c syscall.RawConn) error = nil + if c.Mark > 0 { + controlFunction = func(_, _ string, cc syscall.RawConn) error { + return cc.Control(func(fd uintptr) { + ex := setSocketMark(int(fd), c.Mark) + if ex != nil { + log.Logf("net dialer set mark %d error: %s", c.Mark, ex) + } else { + // log.Logf("net dialer set mark %d success", options.Mark) + } + }) + } + } + + if c.Interface != "" { + controlFunction = func(_, _ string, cc syscall.RawConn) error { + return cc.Control(func(fd uintptr) { + err := setSocketInterface(int(fd), c.Interface) + + if err != nil { + log.Logf("net dialer set interface %s error: %s", c.Interface, err) + } + }) + } + } + if route.IsEmpty() { switch network { case "udp", "udp4", "udp6": @@ -160,6 +200,7 @@ func (c *Chain) dialWithOptions(ctx context.Context, network, address string, op } d := &net.Dialer{ Timeout: timeout, + Control: controlFunction, // LocalAddr: laddr, // TODO: optional local address } return d.DialContext(ctx, network, ipAddr) @@ -193,9 +234,11 @@ func (*Chain) resolve(addr string, resolver Resolver, hosts *Hosts) string { if err != nil { log.Logf("[resolver] %s: %v", host, err) } - if len(ips) > 0 { - return net.JoinHostPort(ips[0].String(), port) + if len(ips) == 0 { + log.Logf("[resolver] %s: domain does not exists", host) + return "" } + return net.JoinHostPort(ips[0].String(), port) } return addr } @@ -286,13 +329,13 @@ func (c *Chain) selectRoute() (route *Chain, err error) { // selectRouteFor selects route with bypass testing. func (c *Chain) selectRouteFor(addr string) (route *Chain, err error) { if c.IsEmpty() { - return newRoute(), nil + return c.newRoute(), nil } if c.isRoute { return c, nil } - route = newRoute() + route = c.newRoute() var nl []Node for _, group := range c.nodeGroups { @@ -310,7 +353,7 @@ func (c *Chain) selectRouteFor(addr string) (route *Chain, err error) { node.DialOptions = append(node.DialOptions, ChainDialOption(route), ) - route = newRoute() // cutoff the chain for multiplex node. + route = c.newRoute() // cutoff the chain for multiplex node. } route.AddNode(node) @@ -328,6 +371,7 @@ type ChainOptions struct { Timeout time.Duration Hosts *Hosts Resolver Resolver + Mark int } // ChainOption allows a common way to set chain options. diff --git a/client.go b/client.go index c840067..90b42bb 100644 --- a/client.go +++ b/client.go @@ -7,7 +7,7 @@ import ( "net/url" "time" - "github.com/ginuerzh/gosocks5" + "github.com/go-gost/gosocks5" ) // Client is a proxy client. diff --git a/cmd/gost/cfg.go b/cmd/gost/cfg.go index b8fda23..dc696c8 100644 --- a/cmd/gost/cfg.go +++ b/cmd/gost/cfg.go @@ -152,17 +152,25 @@ func parseIP(s string, port string) (ips []string) { port = "8080" // default port } + addrFn := func(s, port string) string { + c := strings.Count(s, ":") + if c == 0 || //ipv4 or domain + s[len(s)-1] == ']' { //[ipv6] + return s + ":" + port + } + if c > 1 && s[0] != '[' { // ipv6 + return "[" + s + "]:" + port + } + return s //ipv4:port or [ipv6]:port + } + file, err := os.Open(s) if err != nil { ss := strings.Split(s, ",") for _, s := range ss { s = strings.TrimSpace(s) if s != "" { - // TODO: support IPv6 - if !strings.Contains(s, ":") { - s = s + ":" + port - } - ips = append(ips, s) + ips = append(ips, addrFn(s, port)) } } @@ -175,10 +183,7 @@ func parseIP(s string, port string) (ips []string) { if line == "" || strings.HasPrefix(line, "#") { continue } - if !strings.Contains(line, ":") { - line = line + ":" + port - } - ips = append(ips, line) + ips = append(ips, addrFn(line, port)) } return } diff --git a/cmd/gost/main.go b/cmd/gost/main.go index f08f413..ce9184c 100644 --- a/cmd/gost/main.go +++ b/cmd/gost/main.go @@ -31,7 +31,9 @@ func init() { flag.Var(&baseCfg.route.ChainNodes, "F", "forward address, can make a forward chain") flag.Var(&baseCfg.route.ServeNodes, "L", "listen address, can listen on multiple ports (required)") + flag.IntVar(&baseCfg.route.Mark, "M", 0, "Specify out connection mark") flag.StringVar(&configureFile, "C", "", "configure file") + flag.StringVar(&baseCfg.route.Interface, "I", "", "Interface to bind") flag.BoolVar(&baseCfg.Debug, "D", false, "enable debug log") flag.BoolVar(&printVersion, "V", false, "print version") if pprofEnabled { diff --git a/cmd/gost/route.go b/cmd/gost/route.go index 0db5b2e..7ebbdf9 100644 --- a/cmd/gost/route.go +++ b/cmd/gost/route.go @@ -30,11 +30,15 @@ type route struct { ServeNodes stringList ChainNodes stringList Retries int + Mark int + Interface string } func (r *route) parseChain() (*gost.Chain, error) { chain := gost.NewChain() chain.Retries = r.Retries + chain.Mark = r.Mark + chain.Interface = r.Interface gid := 1 // group ID for _, ns := range r.ChainNodes { @@ -208,6 +212,12 @@ func parseChainNode(ns string) (nodes []gost.Node, err error) { Timeout: timeout, IdleTimeout: node.GetDuration("idle"), } + if config.KeepAlive { + config.KeepAlivePeriod = node.GetDuration("ttl") + if config.KeepAlivePeriod == 0 { + config.KeepAlivePeriod = 10 * time.Second + } + } if cipher := node.Get("cipher"); cipher != "" { sum := sha256.Sum256([]byte(cipher)) @@ -454,6 +464,12 @@ func (r *route) GenRouters() ([]router, error) { Timeout: timeout, IdleTimeout: node.GetDuration("idle"), } + if config.KeepAlive { + config.KeepAlivePeriod = node.GetDuration("ttl") + if config.KeepAlivePeriod == 0 { + config.KeepAlivePeriod = 10 * time.Second + } + } if cipher := node.Get("cipher"); cipher != "" { sum := sha256.Sum256([]byte(cipher)) config.Key = sum[:] @@ -648,6 +664,8 @@ func (r *route) GenRouters() ([]router, error) { gost.IPsHandlerOption(ips), gost.TCPModeHandlerOption(node.GetBool("tcp")), gost.IPRoutesHandlerOption(tunRoutes...), + gost.ProxyAgentHandlerOption(node.Get("proxyAgent")), + gost.HTTPTunnelHandlerOption(node.GetBool("httpTunnel")), ) rt := router{ diff --git a/examples/ssu/ssu.go b/examples/ssu/ssu.go index cae97d0..6aeee1c 100644 --- a/examples/ssu/ssu.go +++ b/examples/ssu/ssu.go @@ -6,7 +6,7 @@ import ( "net" "strconv" - "github.com/ginuerzh/gosocks5" + "github.com/go-gost/gosocks5" ss "github.com/shadowsocks/shadowsocks-go/shadowsocks" ) diff --git a/forward.go b/forward.go index ac54553..9985780 100644 --- a/forward.go +++ b/forward.go @@ -10,7 +10,7 @@ import ( "fmt" - "github.com/ginuerzh/gosocks5" + "github.com/go-gost/gosocks5" "github.com/go-log/log" smux "github.com/xtaci/smux" ) @@ -131,6 +131,7 @@ func (h *tcpDirectForwardHandler) Handle(conn net.Conn) { cc, err = h.options.Chain.Dial(node.Addr, RetryChainOption(h.options.Retries), TimeoutChainOption(h.options.Timeout), + ResolverChainOption(h.options.Resolver), ) if err != nil { log.Logf("[tcp] %s -> %s : %s", conn.RemoteAddr(), conn.LocalAddr(), err) @@ -197,7 +198,12 @@ func (h *udpDirectForwardHandler) Handle(conn net.Conn) { } } - cc, err := h.options.Chain.DialContext(context.Background(), "udp", node.Addr) + cc, err := h.options.Chain.DialContext( + context.Background(), + "udp", + node.Addr, + ResolverChainOption(h.options.Resolver), + ) if err != nil { node.MarkDead() log.Logf("[udp] %s - %s : %s", conn.RemoteAddr(), conn.LocalAddr(), err) diff --git a/go.mod b/go.mod index eed2669..b006564 100644 --- a/go.mod +++ b/go.mod @@ -1,45 +1,60 @@ module github.com/ginuerzh/gost -go 1.16 +go 1.20 + +replace github.com/templexxx/cpu v0.0.7 => github.com/templexxx/cpu v0.0.10-0.20211111114238-98168dcec14a require ( - git.torproject.org/pluggable-transports/goptlib.git v0.0.0-20180321061416-7d56ec4f381e - git.torproject.org/pluggable-transports/obfs4.git v0.0.0-20181103133120-08f4d470188e + git.torproject.org/pluggable-transports/goptlib.git v1.2.0 github.com/LiamHaworth/go-tproxy v0.0.0-20190726054950-ef7efd7f24ed - github.com/Yawning/chacha20 v0.0.0-20170904085104-e3b1f968fc63 // indirect github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d - github.com/bifurcation/mint v0.0.0-20181105071958-a14404e9a861 // indirect - github.com/cheekybits/genny v1.0.0 // indirect - github.com/coreos/go-iptables v0.5.0 // indirect - github.com/docker/libcontainer v2.2.1+incompatible - github.com/ginuerzh/gosocks4 v0.0.1 - github.com/ginuerzh/gosocks5 v0.2.0 - github.com/ginuerzh/tls-dissector v0.0.2-0.20200224064855-24ab2b3a3796 - github.com/go-gost/relay v0.1.0 + github.com/go-gost/gosocks4 v0.0.1 + github.com/go-gost/gosocks5 v0.3.0 + github.com/go-gost/relay v0.1.1-0.20211123134818-8ef7fd81ffd7 + github.com/go-gost/tls-dissector v0.0.2-0.20220408131628-aac992c27451 github.com/go-log/log v0.2.0 github.com/gobwas/glob v0.2.3 - github.com/google/gopacket v1.1.19 // indirect github.com/gorilla/websocket v1.4.2 - github.com/hashicorp/golang-lru v0.5.4 // indirect - github.com/klauspost/compress v1.11.12 - github.com/klauspost/reedsolomon v1.9.12 // indirect - github.com/lucas-clemente/aes12 v0.0.0-20171027163421-cd47fb39b79f // indirect - github.com/lucas-clemente/quic-go v0.10.0 - github.com/lucas-clemente/quic-go-certificates v0.0.0-20160823095156-d2f86524cced // indirect - github.com/miekg/dns v1.1.41 - github.com/milosgajdos/tenus v0.0.3 - github.com/pkg/errors v0.9.1 // indirect + github.com/klauspost/compress v1.13.6 + github.com/miekg/dns v1.1.47 + github.com/quic-go/quic-go v0.32.0 github.com/ryanuber/go-glob v1.0.0 - github.com/shadowsocks/go-shadowsocks2 v0.1.4 - github.com/shadowsocks/shadowsocks-go v0.0.0-20170121203516-97a5c71f80ba + github.com/shadowsocks/go-shadowsocks2 v0.1.5 + github.com/shadowsocks/shadowsocks-go v0.0.0-20200409064450-3e585ff90601 github.com/songgao/water v0.0.0-20200317203138-2b4b6d7c09d8 - github.com/templexxx/cpufeat v0.0.0-20180724012125-cef66df7f161 // indirect - github.com/templexxx/xor v0.0.0-20191217153810-f85b25db303b // indirect - github.com/tjfoc/gmsm v1.4.0 // indirect - github.com/xtaci/kcp-go v5.4.20+incompatible - github.com/xtaci/smux v1.5.15 + github.com/xtaci/kcp-go/v5 v5.6.1 + github.com/xtaci/smux v1.5.16 github.com/xtaci/tcpraw v1.2.25 - golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83 - golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 - golang.org/x/text v0.3.5 // indirect + gitlab.com/yawning/obfs4.git v0.0.0-20220204003609-77af0cba934d + golang.org/x/crypto v0.5.0 + golang.org/x/net v0.7.0 +) + +require ( + filippo.io/edwards25519 v1.0.0-rc.1.0.20210721174708-390f27c3be20 // indirect + github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da // indirect + github.com/coreos/go-iptables v0.6.0 // indirect + github.com/dchest/siphash v1.2.2 // indirect + github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect + github.com/golang/mock v1.6.0 // indirect + github.com/google/gopacket v1.1.19 // indirect + github.com/google/pprof v0.0.0-20230131232505-5a9e8f65f08f // indirect + github.com/klauspost/cpuid/v2 v2.0.9 // indirect + github.com/klauspost/reedsolomon v1.9.15 // indirect + github.com/onsi/ginkgo/v2 v2.8.0 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/quic-go/qtls-go1-18 v0.2.0 // indirect + github.com/quic-go/qtls-go1-19 v0.2.0 // indirect + github.com/quic-go/qtls-go1-20 v0.1.0 // indirect + github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 // indirect + github.com/templexxx/cpu v0.0.7 // indirect + github.com/templexxx/xorsimd v0.4.1 // indirect + github.com/tjfoc/gmsm v1.4.1 // indirect + github.com/xtaci/lossyconn v0.0.0-20200209145036-adba10fffc37 // indirect + gitlab.com/yawning/edwards25519-extra.git v0.0.0-20211229043746-2f91fcc9fbdb // indirect + golang.org/x/exp v0.0.0-20230203172020-98cc5a0785f9 // indirect + golang.org/x/mod v0.7.0 // indirect + golang.org/x/sys v0.5.0 // indirect + golang.org/x/text v0.7.0 // indirect + golang.org/x/tools v0.5.0 // indirect ) diff --git a/go.sum b/go.sum index 0ec51f2..e6ef9f2 100644 --- a/go.sum +++ b/go.sum @@ -1,48 +1,49 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -git.torproject.org/pluggable-transports/goptlib.git v0.0.0-20180321061416-7d56ec4f381e h1:PYcONLFUhr00kGrq7Mf14JRtoXHG7BOSKIfIha0Hu5Q= -git.torproject.org/pluggable-transports/goptlib.git v0.0.0-20180321061416-7d56ec4f381e/go.mod h1:YT4XMSkuEXbtqlydr9+OxqFAyspUv0Gr9qhM3B++o/Q= -git.torproject.org/pluggable-transports/obfs4.git v0.0.0-20181103133120-08f4d470188e h1:c8h60PKrRxEB5debIHBmP7T+s/EUNXTklXqlmJfYiJQ= -git.torproject.org/pluggable-transports/obfs4.git v0.0.0-20181103133120-08f4d470188e/go.mod h1:jRZbfRcLIgFQoCw6tRmsnETVyIj54jOmXhHCYYa0jbs= +filippo.io/edwards25519 v1.0.0-rc.1.0.20210721174708-390f27c3be20 h1:iJoUgXvhagsNMrJrvavw7vu1eG8+hm6jLOxlLFcoODw= +filippo.io/edwards25519 v1.0.0-rc.1.0.20210721174708-390f27c3be20/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns= +git.torproject.org/pluggable-transports/goptlib.git v1.0.0/go.mod h1:YT4XMSkuEXbtqlydr9+OxqFAyspUv0Gr9qhM3B++o/Q= +git.torproject.org/pluggable-transports/goptlib.git v1.2.0 h1:0qRF7Dw5qXd0FtZkjWUiAh5GTutRtDGL4GXUDJ4qMHs= +git.torproject.org/pluggable-transports/goptlib.git v1.2.0/go.mod h1:4PBMl1dg7/3vMWSoWb46eGWlrxkUyn/CAJmxhDLAlDs= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/LiamHaworth/go-tproxy v0.0.0-20190726054950-ef7efd7f24ed h1:eqa6queieK8SvoszxCu0WwH7lSVeL4/N/f1JwOMw1G4= github.com/LiamHaworth/go-tproxy v0.0.0-20190726054950-ef7efd7f24ed/go.mod h1:rA52xkgZwql9LRZXWb2arHEFP6qSR48KY2xOfWzEciQ= -github.com/Yawning/chacha20 v0.0.0-20170904085104-e3b1f968fc63 h1:I6/SJSN9wJMJ+ZyQaCHUlzoTA4ypU5Bb44YWR1wTY/0= -github.com/Yawning/chacha20 v0.0.0-20170904085104-e3b1f968fc63/go.mod h1:nf+Komq6fVP4SwmKEaVGxHTyQGKREVlwjQKpvOV39yE= -github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412 h1:w1UutsfOrms1J05zt7ISrnJIXKzwaspym5BTKGx93EI= -github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412/go.mod h1:WPjqKcmVOxf0XSf3YxCJs6N6AOSrOx3obionmG7T0y0= +github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da h1:KjTM2ks9d14ZYCvmHS9iAKVt9AyzRSqNU1qabPih5BY= +github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da/go.mod h1:eHEWzANqSiWQsof+nXEI9bUVUyV6F53Fp89EuCh2EAA= github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d h1:Byv0BzEl3/e6D5CLfI0j/7hiIEtvGVFPCZ7Ei2oq8iQ= github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= -github.com/bifurcation/mint v0.0.0-20181105071958-a14404e9a861 h1:x17NvoJaphEzay72TFej4OSSsgu3xRYBLkbIwdofS/4= -github.com/bifurcation/mint v0.0.0-20181105071958-a14404e9a861/go.mod h1:zVt7zX3K/aDCk9Tj+VM7YymsX66ERvzCJzw8rFCX2JU= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitfE= -github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/coreos/go-iptables v0.5.0 h1:mw6SAibtHKZcNzAsOxjoHIG0gy5YFHhypWSSNc6EjbQ= -github.com/coreos/go-iptables v0.5.0/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU= -github.com/dchest/siphash v1.2.0 h1:YWOShuhvg0GqbQpMa60QlCGtEyf7O7HC1Jf0VjdQ60M= -github.com/dchest/siphash v1.2.0/go.mod h1:q+IRvb2gOSrUnYoPqHiyHXS0FOBBOdl6tONBlVnOnt4= -github.com/docker/libcontainer v1.4.0 h1:mrCCYnQU1lnp43y/1ViKbGjucA+Txbmf7hPIdC8+r7A= -github.com/docker/libcontainer v2.2.1+incompatible h1:++SbbkCw+X8vAd4j2gOCzZ2Nn7s2xFALTf7LZKmM1/0= -github.com/docker/libcontainer v2.2.1+incompatible/go.mod h1:osvj61pYsqhNCMLGX31xr7klUBhHb/ZBuXS0o1Fvwbw= +github.com/coreos/go-iptables v0.6.0 h1:is9qnZMPYjLd8LYqmm/qlE+wwEgJIkTYdhV3rfZo4jk= +github.com/coreos/go-iptables v0.6.0/go.mod h1:Qe8Bv2Xik5FyTXwgIbLAnv2sWSBmvWdFETJConOQ//Q= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dchest/siphash v1.2.1/go.mod h1:q+IRvb2gOSrUnYoPqHiyHXS0FOBBOdl6tONBlVnOnt4= +github.com/dchest/siphash v1.2.2 h1:9DFz8tQwl9pTVt5iok/9zKyzA1Q6bRGiF3HPiEEVr9I= +github.com/dchest/siphash v1.2.2/go.mod h1:q+IRvb2gOSrUnYoPqHiyHXS0FOBBOdl6tONBlVnOnt4= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/ginuerzh/gosocks4 v0.0.1 h1:ojDKUyz+uaEeRm2usY1cyQiXTqJqrKxfeE6SVBXq4m0= -github.com/ginuerzh/gosocks4 v0.0.1/go.mod h1:8SdwBMKjfJ9+BfP2vDJM1jcrgWUbWV6qxBPHHVrwptY= -github.com/ginuerzh/gosocks5 v0.2.0 h1:K0Ua23U9LU3BZrf3XpGDcs0mP8DiEpa6PJE4TA/MU3s= -github.com/ginuerzh/gosocks5 v0.2.0/go.mod h1:qp22mr6tH/prEoaN0pFukq76LlScIE+F2rP2ZP5ZHno= -github.com/ginuerzh/tls-dissector v0.0.2-0.20200224064855-24ab2b3a3796 h1:VPXbYRvZUzTemsI7u0FzOnEuHeHwQuMTPXApAu8aeX4= -github.com/ginuerzh/tls-dissector v0.0.2-0.20200224064855-24ab2b3a3796/go.mod h1:YyzP8PQrGwDH/XsfHJXwqdHLwWvBYxu77YVKm0+68f0= -github.com/go-gost/relay v0.1.0 h1:UOf2YwAzzaUjY5mdpMuLfSw0vz62iIFYk7oJQkuhlGw= -github.com/go-gost/relay v0.1.0/go.mod h1:YFCpddLOFE3NlIkeDWRdEs8gL/GFsqXdtaf8SV5v4YQ= +github.com/go-gost/gosocks4 v0.0.1 h1:+k1sec8HlELuQV7rWftIkmy8UijzUt2I6t+iMPlGB2s= +github.com/go-gost/gosocks4 v0.0.1/go.mod h1:3B6L47HbU/qugDg4JnoFPHgJXE43Inz8Bah1QaN9qCc= +github.com/go-gost/gosocks5 v0.3.0 h1:Hkmp9YDRBSCJd7xywW6dBPT6B9aQTkuWd+3WCheJiJA= +github.com/go-gost/gosocks5 v0.3.0/go.mod h1:1G6I7HP7VFVxveGkoK8mnprnJqSqJjdcASKsdUn4Pp4= +github.com/go-gost/relay v0.1.1-0.20211123134818-8ef7fd81ffd7 h1:itaaJhQJ19kUXEB4Igb0EbY8m+1Py2AaNNSBds/9gk4= +github.com/go-gost/relay v0.1.1-0.20211123134818-8ef7fd81ffd7/go.mod h1:lcX+23LCQ3khIeASBo+tJ/WbwXFO32/N5YN6ucuYTG8= +github.com/go-gost/tls-dissector v0.0.2-0.20220408131628-aac992c27451 h1:xj8gUZGYO3nb5+6Bjw9+tsFkA9sYynrOvDvvC4uDV2I= +github.com/go-gost/tls-dissector v0.0.2-0.20220408131628-aac992c27451/go.mod h1:/9QfdewqmHdaE362Hv5nDaSWLx3pCmtD870d6GaquXs= github.com/go-log/log v0.2.0 h1:z8i91GBudxD5L3RmF0KVpetCbcGWAV7q1Tw1eRwQM9Q= github.com/go-log/log v0.2.0/go.mod h1:xzCnwajcues/6w7lne3yK2QU7DBPW7kqbgPGG5AF65U= +github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= @@ -52,110 +53,172 @@ github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrU github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8= github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo= +github.com/google/pprof v0.0.0-20230131232505-5a9e8f65f08f h1:gl1DCiSk+mrXXBGPm6CEeS2MkJuMVzAOrXg34oVj1QI= +github.com/google/pprof v0.0.0-20230131232505-5a9e8f65f08f/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo= github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= -github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= -github.com/klauspost/compress v1.11.12 h1:famVnQVu7QwryBN4jNseQdUKES71ZAOnB6UQQJPZvqk= -github.com/klauspost/compress v1.11.12/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= -github.com/klauspost/cpuid/v2 v2.0.2 h1:pd2FBxFydtPn2ywTLStbFg9CJKrojATnpeJWSP7Ys4k= -github.com/klauspost/cpuid/v2 v2.0.2/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= -github.com/klauspost/reedsolomon v1.9.12 h1:EyOucRmcrLH+2hqKGdoA5SM8pwPKR6BJsf3r6zpYOA0= -github.com/klauspost/reedsolomon v1.9.12/go.mod h1:nLvuzNvy1ZDNQW30IuMc2ZWCbiqrJgdLoUS2X8HAUVg= -github.com/lucas-clemente/aes12 v0.0.0-20171027163421-cd47fb39b79f h1:sSeNEkJrs+0F9TUau0CgWTTNEwF23HST3Eq0A+QIx+A= -github.com/lucas-clemente/aes12 v0.0.0-20171027163421-cd47fb39b79f/go.mod h1:JpH9J1c9oX6otFSgdUHwUBUizmKlrMjxWnIAjff4m04= -github.com/lucas-clemente/quic-go v0.10.0 h1:xEF+pSHYAOcu+U10Meunf+DTtc8vhQDRqlA0BJ6hufc= -github.com/lucas-clemente/quic-go v0.10.0/go.mod h1:wuD+2XqEx8G9jtwx5ou2BEYBsE+whgQmlj0Vz/77PrY= -github.com/lucas-clemente/quic-go-certificates v0.0.0-20160823095156-d2f86524cced h1:zqEC1GJZFbGZA0tRyNZqRjep92K5fujFtFsu5ZW7Aug= -github.com/lucas-clemente/quic-go-certificates v0.0.0-20160823095156-d2f86524cced/go.mod h1:NCcRLrOTZbzhZvixZLlERbJtDtYsmMw8Jc4vS8Z0g58= -github.com/miekg/dns v1.1.41 h1:WMszZWJG0XmzbK9FEmzH2TVcqYzFesusSIB41b8KHxY= -github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= -github.com/milosgajdos/tenus v0.0.3 h1:jmaJzwaY1DUyYVD0lM4U+uvP2kkEg1VahDqRFxIkVBE= -github.com/milosgajdos/tenus v0.0.3/go.mod h1:eIjx29vNeDOYWJuCnaHY2r4fq5egetV26ry3on7p8qY= +github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc= +github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= +github.com/klauspost/cpuid v1.2.4/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= +github.com/klauspost/cpuid v1.3.1/go.mod h1:bYW4mA6ZgKPob1/Dlai2LviZJO7KGI3uoWLd42rAQw4= +github.com/klauspost/cpuid/v2 v2.0.6/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4= +github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/klauspost/reedsolomon v1.9.9/go.mod h1:O7yFFHiQwDR6b2t63KPUpccPtNdp5ADgh1gg4fd12wo= +github.com/klauspost/reedsolomon v1.9.15 h1:g2erWKD2M6rgnPf89fCji6jNlhMKMdXcuNHMW1SYCIo= +github.com/klauspost/reedsolomon v1.9.15/go.mod h1:eqPAcE7xar5CIzcdfwydOEdcmchAKAP/qs14y4GCBOk= +github.com/miekg/dns v1.1.47 h1:J9bWiXbqMbnZPcY8Qi2E3EWIBsIm6MZzzJB9VRg5gL8= +github.com/miekg/dns v1.1.47/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME= +github.com/mmcloughlin/avo v0.0.0-20200803215136-443f81d77104/go.mod h1:wqKykBG2QzQDJEzvRkcS8x6MiSJkF52hXZsXcjaB3ls= +github.com/onsi/ginkgo/v2 v2.8.0 h1:pAM+oBNPrpXRs+E/8spkeGx9QgekbRVyr74EUvRVOUI= +github.com/onsi/ginkgo/v2 v2.8.0/go.mod h1:6JsQiECmxCa3V5st74AL/AmsV482EDdVrGaVW6z3oYU= +github.com/onsi/gomega v1.25.0 h1:Vw7br2PCDYijJHSfBOWhov+8cAnUf8MfMaIOV323l6Y= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/quic-go/qtls-go1-18 v0.2.0 h1:5ViXqBZ90wpUcZS0ge79rf029yx0dYB0McyPJwqqj7U= +github.com/quic-go/qtls-go1-18 v0.2.0/go.mod h1:moGulGHK7o6O8lSPSZNoOwcLvJKJ85vVNc7oJFD65bc= +github.com/quic-go/qtls-go1-19 v0.2.0 h1:Cvn2WdhyViFUHoOqK52i51k4nDX8EwIh5VJiVM4nttk= +github.com/quic-go/qtls-go1-19 v0.2.0/go.mod h1:ySOI96ew8lnoKPtSqx2BlI5wCpUVPT05RMAlajtnyOI= +github.com/quic-go/qtls-go1-20 v0.1.0 h1:d1PK3ErFy9t7zxKsG3NXBJXZjp/kMLoIb3y/kV54oAI= +github.com/quic-go/qtls-go1-20 v0.1.0/go.mod h1:JKtK6mjbAVcUTN/9jZpvLbGxvdWIKS8uT7EiStoU1SM= +github.com/quic-go/quic-go v0.32.0 h1:lY02md31s1JgPiiyfqJijpu/UX/Iun304FI3yUqX7tA= +github.com/quic-go/quic-go v0.32.0/go.mod h1:/fCsKANhQIeD5l76c2JFU+07gVE3KaA0FP+0zMWwfwo= github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 h1:f/FNXud6gA3MNr8meMVVGxhp+QBTqY91tM8HjEuMjGg= github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3/go.mod h1:HgjTstvQsPGkxUsCd2KWxErBblirPizecHcpD3ffK+s= github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk= github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= -github.com/shadowsocks/go-shadowsocks2 v0.1.4 h1:4VzajPL7RwwmImysBSvI+lm/UaegDGQq3hr42dYo3gs= -github.com/shadowsocks/go-shadowsocks2 v0.1.4/go.mod h1:AGGpIoek4HRno4xzyFiAtLHkOpcoznZEkAccaI/rplM= -github.com/shadowsocks/shadowsocks-go v0.0.0-20170121203516-97a5c71f80ba h1:tJgNXb3S+RkB4kNPi6N5OmEWe3m+Y3Qs6LUMiNDAONM= -github.com/shadowsocks/shadowsocks-go v0.0.0-20170121203516-97a5c71f80ba/go.mod h1:mttDPaeLm87u74HMrP+n2tugXvIKWcwff/cqSX0lehY= +github.com/shadowsocks/go-shadowsocks2 v0.1.5 h1:PDSQv9y2S85Fl7VBeOMF9StzeXZyK1HakRm86CUbr28= +github.com/shadowsocks/go-shadowsocks2 v0.1.5/go.mod h1:AGGpIoek4HRno4xzyFiAtLHkOpcoznZEkAccaI/rplM= +github.com/shadowsocks/shadowsocks-go v0.0.0-20200409064450-3e585ff90601 h1:XU9hik0exChEmY92ALW4l9WnDodxLVS9yOSNh2SizaQ= +github.com/shadowsocks/shadowsocks-go v0.0.0-20200409064450-3e585ff90601/go.mod h1:mttDPaeLm87u74HMrP+n2tugXvIKWcwff/cqSX0lehY= github.com/songgao/water v0.0.0-20200317203138-2b4b6d7c09d8 h1:TG/diQgUe0pntT/2D9tmUCz4VNwm9MfrtPr0SU2qSX8= github.com/songgao/water v0.0.0-20200317203138-2b4b6d7c09d8/go.mod h1:P5HUIBuIWKbyjl083/loAegFkfbFNx5i2qEP4CNbm7E= -github.com/templexxx/cpufeat v0.0.0-20180724012125-cef66df7f161 h1:89CEmDvlq/F7SJEOqkIdNDGJXrQIhuIx9D2DBXjavSU= -github.com/templexxx/cpufeat v0.0.0-20180724012125-cef66df7f161/go.mod h1:wM7WEvslTq+iOEAMDLSzhVuOt5BRZ05WirO+b09GHQU= -github.com/templexxx/xor v0.0.0-20191217153810-f85b25db303b h1:fj5tQ8acgNUr6O8LEplsxDhUIe2573iLkJc+PqnzZTI= -github.com/templexxx/xor v0.0.0-20191217153810-f85b25db303b/go.mod h1:5XA7W9S6mni3h5uvOC75dA3m9CCCaS83lltmc0ukdi4= -github.com/tjfoc/gmsm v1.4.0 h1:8nbaiZG+iVdh+fXVw0DZoZZa7a4TGm3Qab+xdrdzj8s= -github.com/tjfoc/gmsm v1.4.0/go.mod h1:j4INPkHWMrhJb38G+J6W4Tw0AbuN8Thu3PbdVYhVcTE= -github.com/xtaci/kcp-go v1.0.1 h1:SEZn2Iick6ualQpV8yY9cXdDTgbfBHPIwJl7UvxfxLQ= -github.com/xtaci/kcp-go v5.4.20+incompatible h1:TN1uey3Raw0sTz0Fg8GkfM0uH3YwzhnZWQ1bABv5xAg= -github.com/xtaci/kcp-go v5.4.20+incompatible/go.mod h1:bN6vIwHQbfHaHtFpEssmWsN45a+AZwO7eyRCmEIbtvE= -github.com/xtaci/smux v1.5.15 h1:6hMiXswcleXj5oNfcJc+DXS8Vj36XX2LaX98udog6Kc= -github.com/xtaci/smux v1.5.15/go.mod h1:OMlQbT5vcgl2gb49mFkYo6SMf+zP3rcjcwQz7ZU7IGY= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/templexxx/cpu v0.0.1/go.mod h1:w7Tb+7qgcAlIyX4NhLuDKt78AHA5SzPmq0Wj6HiEnnk= +github.com/templexxx/cpu v0.0.10-0.20211111114238-98168dcec14a h1:f0GQM8LuKYnXdNLcAg+di6PULSlR5iQtZT3bDwDRiA0= +github.com/templexxx/cpu v0.0.10-0.20211111114238-98168dcec14a/go.mod h1:w7Tb+7qgcAlIyX4NhLuDKt78AHA5SzPmq0Wj6HiEnnk= +github.com/templexxx/xorsimd v0.4.1 h1:iUZcywbOYDRAZUasAs2eSCUW8eobuZDy0I9FJiORkVg= +github.com/templexxx/xorsimd v0.4.1/go.mod h1:W+ffZz8jJMH2SXwuKu9WhygqBMbFnp14G2fqEr8qaNo= +github.com/tjfoc/gmsm v1.3.2/go.mod h1:HaUcFuY0auTiaHB9MHFGCPx5IaLhTUd2atbCFBQXn9w= +github.com/tjfoc/gmsm v1.4.1 h1:aMe1GlZb+0bLjn+cKTPEvvn9oUEBlJitaZiiBwsbgho= +github.com/tjfoc/gmsm v1.4.1/go.mod h1:j4INPkHWMrhJb38G+J6W4Tw0AbuN8Thu3PbdVYhVcTE= +github.com/xtaci/kcp-go/v5 v5.6.1 h1:Pwn0aoeNSPF9dTS7IgiPXn0HEtaIlVb6y5UKWPsx8bI= +github.com/xtaci/kcp-go/v5 v5.6.1/go.mod h1:W3kVPyNYwZ06p79dNwFWQOVFrdcBpDBsdyvK8moQrYo= +github.com/xtaci/lossyconn v0.0.0-20190602105132-8df528c0c9ae/go.mod h1:gXtu8J62kEgmN++bm9BVICuT/e8yiLI2KFobd/TRFsE= +github.com/xtaci/lossyconn v0.0.0-20200209145036-adba10fffc37 h1:EWU6Pktpas0n8lLQwDsRyZfmkPeRbdgPtW609es+/9E= +github.com/xtaci/lossyconn v0.0.0-20200209145036-adba10fffc37/go.mod h1:HpMP7DB2CyokmAh4lp0EQnnWhmycP/TvwBGzvuie+H0= +github.com/xtaci/smux v1.5.16 h1:FBPYOkW8ZTjLKUM4LI4xnnuuDC8CQ/dB04HD519WoEk= +github.com/xtaci/smux v1.5.16/go.mod h1:OMlQbT5vcgl2gb49mFkYo6SMf+zP3rcjcwQz7ZU7IGY= github.com/xtaci/tcpraw v1.2.25 h1:VDlqo0op17JeXBM6e2G9ocCNLOJcw9mZbobMbJjo0vk= github.com/xtaci/tcpraw v1.2.25/go.mod h1:dKyZ2V75s0cZ7cbgJYdxPvms7af0joIeOyx1GgJQbLk= -golang.org/x/crypto v0.0.0-20181015023909-0c41d7ab0a0e h1:IzypfodbhbnViNUO/MEh0FzCUooG97cIGfdggUrUSyU= -golang.org/x/crypto v0.0.0-20181015023909-0c41d7ab0a0e/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +gitlab.com/yawning/edwards25519-extra.git v0.0.0-20211229043746-2f91fcc9fbdb h1:qRSZHsODmAP5qDvb3YsO7Qnf3TRiVbGxNG/WYnlM4/o= +gitlab.com/yawning/edwards25519-extra.git v0.0.0-20211229043746-2f91fcc9fbdb/go.mod h1:gvdJuZuO/tPZyhEV8K3Hmoxv/DWud5L4qEQxfYjEUTo= +gitlab.com/yawning/obfs4.git v0.0.0-20220204003609-77af0cba934d h1:tJ8F7ABaQ3p3wjxwXiWSktVDgjZEXkvaRawd2rIq5ws= +gitlab.com/yawning/obfs4.git v0.0.0-20220204003609-77af0cba934d/go.mod h1:9GcM8QNU9/wXtEEH2q8bVOnPI7FtIF6VVLzZ1l6Hgf8= +golang.org/x/arch v0.0.0-20190909030613-46d78d1859ac/go.mod h1:flIaEI6LNU6xOCD5PaJvn9wGP0agmIOqjrtsKGRguv4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191219195013-becbf705a915/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83 h1:/ZScEX8SfEmUGRHs0gxpqteO5nfNW6axyZbBdw9A12g= golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= +golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE= +golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20230203172020-98cc5a0785f9 h1:frX3nT9RkKybPnjyI+yvZh6ZucTZatCCEm9D47sZ2zo= +golang.org/x/exp v0.0.0-20230203172020-98cc5a0785f9/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.7.0 h1:LapD9S96VoQRhi/GrNTqeBJFrUjs5UHCAtTlgwA5oZA= +golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1 h1:Y/KGZSOdz/2r0WJ9Mkmz6NJBusp0kiNx1Cn82lzJQ6w= -golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 h1:qWPm9rbaAMKs8Bq/9LRpbMqxWRVUAQwMI9fVrssnTfw= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200808120158-1030fc2bf1d9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210303074136-134d130e1a04 h1:cEhElsAv9LUt9ZUUocxzWe05oFLVd+AA2nstydTeI8g= -golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.5.0 h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ= -golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200425043458-8463f397d07c/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200808161706-5bf02b21f123/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.5.0 h1:+bSpV5HIeWkuvgaMfI3UmKRThoTA5ODJTUd8T17NO+4= +golang.org/x/tools v0.5.0/go.mod h1:N+Kgy78s5I24c24dU8OfWNEotWjutIs8SnJvn5IDq+k= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= @@ -170,5 +233,11 @@ google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQ google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= diff --git a/gost.go b/gost.go index 1894b84..70633d5 100644 --- a/gost.go +++ b/gost.go @@ -20,7 +20,7 @@ import ( ) // Version is the gost version. -const Version = "2.11.1" +const Version = "2.11.5" // Debug is a flag that enables the debug log. var Debug bool @@ -80,6 +80,8 @@ var ( // DefaultUserAgent is the default HTTP User-Agent header used by HTTP and websocket. DefaultUserAgent = "Chrome/78.0.3904.106" + DefaultProxyAgent = "gost/" + Version + // DefaultMTU is the default mtu for tun/tap device DefaultMTU = 1350 ) diff --git a/gost.png b/gost.png new file mode 100644 index 0000000..6bdc643 Binary files /dev/null and b/gost.png differ diff --git a/handler.go b/handler.go index db53147..ee82cea 100644 --- a/handler.go +++ b/handler.go @@ -7,8 +7,8 @@ import ( "net/url" "time" - "github.com/ginuerzh/gosocks4" - "github.com/ginuerzh/gosocks5" + "github.com/go-gost/gosocks4" + "github.com/go-gost/gosocks5" "github.com/go-log/log" ) @@ -42,6 +42,8 @@ type HandlerOptions struct { IPs []string TCPMode bool IPRoutes []IPRoute + ProxyAgent string + HTTPTunnel bool } // HandlerOption allows a common way to set handler options. @@ -211,6 +213,20 @@ func IPRoutesHandlerOption(routes ...IPRoute) HandlerOption { } } +// ProxyAgentHandlerOption sets the proxy agent for http handler. +func ProxyAgentHandlerOption(agent string) HandlerOption { + return func(opts *HandlerOptions) { + opts.ProxyAgent = agent + } +} + +// HTTPTunnelHandlerOption sets the Tunnel mode for HTTP client used in HTTP handler. +func HTTPTunnelHandlerOption(tunnelMode bool) HandlerOption { + return func(opts *HandlerOptions) { + opts.HTTPTunnel = tunnelMode + } +} + type autoHandler struct { options *HandlerOptions } diff --git a/http.go b/http.go index 1b17e6f..02a7ad3 100644 --- a/http.go +++ b/http.go @@ -173,7 +173,12 @@ func (h *httpHandler) handleRequest(conn net.Conn, req *http.Request) { ProtoMinor: 1, Header: http.Header{}, } - resp.Header.Add("Proxy-Agent", "gost/"+Version) + + proxyAgent := DefaultProxyAgent + if h.options.ProxyAgent != "" { + proxyAgent = h.options.ProxyAgent + } + resp.Header.Add("Proxy-Agent", proxyAgent) if !Can("tcp", host, h.options.Whitelist, h.options.Blacklist) { log.Logf("[http] %s - %s : Unauthorized to tcp connect to %s", @@ -252,7 +257,9 @@ func (h *httpHandler) handleRequest(conn net.Conn, req *http.Request) { // forward http request lastNode := route.LastNode() - if req.Method != http.MethodConnect && lastNode.Protocol == "http" { + if req.Method != http.MethodConnect && + lastNode.Protocol == "http" && + !h.options.HTTPTunnel { err = h.forwardRequest(conn, req, route) if err == nil { return @@ -287,7 +294,7 @@ func (h *httpHandler) handleRequest(conn net.Conn, req *http.Request) { if req.Method == http.MethodConnect { b := []byte("HTTP/1.1 200 Connection established\r\n" + - "Proxy-Agent: gost/" + Version + "\r\n\r\n") + "Proxy-Agent: " + proxyAgent + "\r\n\r\n") if Debug { log.Logf("[http] %s <- %s\n%s", conn.RemoteAddr(), conn.LocalAddr(), string(b)) } diff --git a/http2.go b/http2.go index 1c3cf5a..72c4890 100644 --- a/http2.go +++ b/http2.go @@ -365,7 +365,11 @@ func (h *http2Handler) roundTrip(w http.ResponseWriter, r *http.Request) { log.Logf("[http2] %s - %s\n%s", r.RemoteAddr, laddr, string(dump)) } - w.Header().Set("Proxy-Agent", "gost/"+Version) + proxyAgent := DefaultProxyAgent + if h.options.ProxyAgent != "" { + proxyAgent = h.options.ProxyAgent + } + w.Header().Set("Proxy-Agent", proxyAgent) if !Can("tcp", host, h.options.Whitelist, h.options.Blacklist) { log.Logf("[http2] %s - %s : Unauthorized to tcp connect to %s", diff --git a/kcp.go b/kcp.go index f2ec3fd..573c91f 100644 --- a/kcp.go +++ b/kcp.go @@ -15,9 +15,9 @@ import ( "github.com/go-log/log" "github.com/klauspost/compress/snappy" - "github.com/xtaci/tcpraw" - "github.com/xtaci/kcp-go" + "github.com/xtaci/kcp-go/v5" "github.com/xtaci/smux" + "github.com/xtaci/tcpraw" ) var ( @@ -43,6 +43,9 @@ type KCPConfig struct { Resend int `json:"resend"` NoCongestion int `json:"nc"` SockBuf int `json:"sockbuf"` + SmuxBuf int `json:"smuxbuf"` + StreamBuf int `json:"streambuf"` + SmuxVer int `json:"smuxver"` KeepAlive int `json:"keepalive"` SnmpLog string `json:"snmplog"` SnmpPeriod int `json:"snmpperiod"` @@ -62,6 +65,16 @@ func (c *KCPConfig) Init() { case "fast3": c.NoDelay, c.Interval, c.Resend, c.NoCongestion = 1, 10, 2, 1 } + if c.SmuxVer <= 0 { + c.SmuxVer = 1 + } + if c.SmuxBuf <= 0 { + c.SmuxBuf = c.SockBuf + } + if c.StreamBuf <= 0 { + c.StreamBuf = c.SockBuf / 2 + } + log.Logf("%#v", c) } var ( @@ -83,6 +96,9 @@ var ( Resend: 0, NoCongestion: 0, SockBuf: 4194304, + SmuxVer: 1, + SmuxBuf: 4194304, + StreamBuf: 2097152, KeepAlive: 10, SnmpLog: "", SnmpPeriod: 60, @@ -231,8 +247,14 @@ func (tr *kcpTransporter) initSession(addr string, conn net.Conn, config *KCPCon // stream multiplex smuxConfig := smux.DefaultConfig() - smuxConfig.MaxReceiveBuffer = config.SockBuf + smuxConfig.Version = config.SmuxVer + smuxConfig.MaxReceiveBuffer = config.SmuxBuf + smuxConfig.MaxStreamBuffer = config.StreamBuf smuxConfig.KeepAliveInterval = time.Duration(config.KeepAlive) * time.Second + if err := smux.VerifyConfig(smuxConfig); err != nil { + return nil, err + } + var cc net.Conn = kcpconn if !config.NoComp { cc = newCompStreamConn(kcpconn) @@ -332,7 +354,9 @@ func (l *kcpListener) listenLoop() { func (l *kcpListener) mux(conn net.Conn) { smuxConfig := smux.DefaultConfig() - smuxConfig.MaxReceiveBuffer = l.config.SockBuf + smuxConfig.Version = l.config.SmuxVer + smuxConfig.MaxReceiveBuffer = l.config.SmuxBuf + smuxConfig.MaxStreamBuffer = l.config.StreamBuf smuxConfig.KeepAliveInterval = time.Duration(l.config.KeepAlive) * time.Second log.Logf("[kcp] %s - %s", conn.RemoteAddr(), l.Addr()) @@ -473,9 +497,13 @@ func (c *compStreamConn) Read(b []byte) (n int, err error) { } func (c *compStreamConn) Write(b []byte) (n int, err error) { - n, err = c.w.Write(b) - err = c.w.Flush() - return n, err + if _, err = c.w.Write(b); err != nil { + return 0, err + } + if err = c.w.Flush(); err != nil { + return 0, err + } + return len(b), err } func (c *compStreamConn) Close() error { diff --git a/obfs.go b/obfs.go index 4454684..47062f2 100644 --- a/obfs.go +++ b/obfs.go @@ -20,9 +20,9 @@ import ( "github.com/go-log/log" pt "git.torproject.org/pluggable-transports/goptlib.git" - "git.torproject.org/pluggable-transports/obfs4.git/transports/base" - "git.torproject.org/pluggable-transports/obfs4.git/transports/obfs4" - dissector "github.com/ginuerzh/tls-dissector" + dissector "github.com/go-gost/tls-dissector" + "gitlab.com/yawning/obfs4.git/transports/base" + "gitlab.com/yawning/obfs4.git/transports/obfs4" ) const ( @@ -804,6 +804,16 @@ func Obfs4Listener(addr string) (Listener, error) { return l, nil } +// TempError satisfies the net.Error interface and presents itself +// as temporary to make sure that it gets retried by the Accept loop +// in server.go. +type TempError struct { + error +} + +func (e TempError) Timeout() bool { return false } +func (e TempError) Temporary() bool { return true } + func (l *obfs4Listener) Accept() (net.Conn, error) { conn, err := l.Listener.Accept() if err != nil { @@ -812,7 +822,7 @@ func (l *obfs4Listener) Accept() (net.Conn, error) { cc, err := obfs4ServerConn(l.addr, conn) if err != nil { conn.Close() - return nil, err + return nil, TempError{err} } return cc, nil } diff --git a/quic.go b/quic.go index 1e7cf4d..67b83d3 100644 --- a/quic.go +++ b/quic.go @@ -1,6 +1,7 @@ package gost import ( + "context" "crypto/aes" "crypto/cipher" "crypto/rand" @@ -12,16 +13,15 @@ import ( "time" "github.com/go-log/log" - quic "github.com/lucas-clemente/quic-go" + quic "github.com/quic-go/quic-go" ) type quicSession struct { - conn net.Conn - session quic.Session + session quic.EarlyConnection } func (session *quicSession) GetConn() (*quicConn, error) { - stream, err := session.session.OpenStreamSync() + stream, err := session.session.OpenStreamSync(context.Background()) if err != nil { return nil, err } @@ -33,7 +33,7 @@ func (session *quicSession) GetConn() (*quicConn, error) { } func (session *quicSession) Close() error { - return session.session.Close() + return session.session.CloseWithError(quic.ApplicationErrorCode(0), "closed") } type quicTransporter struct { @@ -59,100 +59,71 @@ func (tr *quicTransporter) Dial(addr string, options ...DialOption) (conn net.Co option(opts) } + udpAddr, err := net.ResolveUDPAddr("udp", addr) + if err != nil { + return nil, err + } + tr.sessionMutex.Lock() defer tr.sessionMutex.Unlock() session, ok := tr.sessions[addr] if !ok { - var cc *net.UDPConn - cc, err = net.ListenUDP("udp", &net.UDPAddr{IP: net.IPv4zero, Port: 0}) + var pc net.PacketConn + pc, err = net.ListenUDP("udp", &net.UDPAddr{IP: net.IPv4zero, Port: 0}) if err != nil { return } - conn = cc if tr.config != nil && tr.config.Key != nil { - conn = &quicCipherConn{UDPConn: cc, key: tr.config.Key} + pc = &quicCipherConn{PacketConn: pc, key: tr.config.Key} } - session = &quicSession{conn: conn} + session, err = tr.initSession(udpAddr, pc) + if err != nil { + pc.Close() + return nil, err + } tr.sessions[addr] = session } - return session.conn, nil + + conn, err = session.GetConn() + if err != nil { + session.Close() + delete(tr.sessions, addr) + return nil, err + } + return conn, nil } func (tr *quicTransporter) Handshake(conn net.Conn, options ...HandshakeOption) (net.Conn, error) { - opts := &HandshakeOptions{} - for _, option := range options { - option(opts) - } + return conn, nil +} + +func (tr *quicTransporter) initSession(addr net.Addr, conn net.PacketConn) (*quicSession, error) { config := tr.config - if opts.QUICConfig != nil { - config = opts.QUICConfig + if config == nil { + config = &QUICConfig{} } if config.TLSConfig == nil { config.TLSConfig = &tls.Config{InsecureSkipVerify: true} } - tr.sessionMutex.Lock() - defer tr.sessionMutex.Unlock() - - timeout := opts.Timeout - if timeout <= 0 { - timeout = HandshakeTimeout - } - conn.SetDeadline(time.Now().Add(timeout)) - defer conn.SetDeadline(time.Time{}) - - session, ok := tr.sessions[opts.Addr] - if session != nil && session.conn != conn { - conn.Close() - return nil, errors.New("quic: unrecognized connection") - } - if !ok || session.session == nil { - s, err := tr.initSession(opts.Addr, conn, config) - if err != nil { - conn.Close() - delete(tr.sessions, opts.Addr) - return nil, err - } - session = s - tr.sessions[opts.Addr] = session - } - cc, err := session.GetConn() - if err != nil { - session.Close() - delete(tr.sessions, opts.Addr) - return nil, err - } - - return cc, nil -} - -func (tr *quicTransporter) initSession(addr string, conn net.Conn, config *QUICConfig) (*quicSession, error) { - udpConn, ok := conn.(net.PacketConn) - if !ok { - return nil, errors.New("quic: wrong connection type") - } - udpAddr, err := net.ResolveUDPAddr("udp", addr) - if err != nil { - return nil, err - } quicConfig := &quic.Config{ - HandshakeTimeout: config.Timeout, - KeepAlive: config.KeepAlive, - IdleTimeout: config.IdleTimeout, + HandshakeIdleTimeout: config.Timeout, + MaxIdleTimeout: config.IdleTimeout, + KeepAlivePeriod: config.KeepAlivePeriod, Versions: []quic.VersionNumber{ - quic.VersionGQUIC43, - quic.VersionGQUIC39, + quic.Version1, + quic.VersionDraft29, }, } - session, err := quic.Dial(udpConn, udpAddr, addr, config.TLSConfig, quicConfig) + session, err := quic.DialEarly(conn, addr, addr.String(), tlsConfigQUICALPN(config.TLSConfig), quicConfig) if err != nil { log.Logf("quic dial %s: %v", addr, err) return nil, err } - return &quicSession{conn: conn, session: session}, nil + return &quicSession{session: session}, nil } func (tr *quicTransporter) Multiplex() bool { @@ -161,15 +132,16 @@ func (tr *quicTransporter) Multiplex() bool { // QUICConfig is the config for QUIC client and server type QUICConfig struct { - TLSConfig *tls.Config - Timeout time.Duration - KeepAlive bool - IdleTimeout time.Duration - Key []byte + TLSConfig *tls.Config + Timeout time.Duration + KeepAlive bool + KeepAlivePeriod time.Duration + IdleTimeout time.Duration + Key []byte } type quicListener struct { - ln quic.Listener + ln quic.EarlyListener connChan chan net.Conn errChan chan error } @@ -180,33 +152,35 @@ func QUICListener(addr string, config *QUICConfig) (Listener, error) { config = &QUICConfig{} } quicConfig := &quic.Config{ - HandshakeTimeout: config.Timeout, - KeepAlive: config.KeepAlive, - IdleTimeout: config.IdleTimeout, + HandshakeIdleTimeout: config.Timeout, + KeepAlivePeriod: config.KeepAlivePeriod, + MaxIdleTimeout: config.IdleTimeout, + Versions: []quic.VersionNumber{ + quic.Version1, + quic.VersionDraft29, + }, } tlsConfig := config.TLSConfig if tlsConfig == nil { tlsConfig = DefaultTLSConfig } - var conn net.PacketConn udpAddr, err := net.ResolveUDPAddr("udp", addr) if err != nil { return nil, err } - lconn, err := net.ListenUDP("udp", udpAddr) + conn, err = net.ListenUDP("udp", udpAddr) if err != nil { return nil, err } - conn = lconn if config.Key != nil { - conn = &quicCipherConn{UDPConn: lconn, key: config.Key} + conn = &quicCipherConn{PacketConn: conn, key: config.Key} } - ln, err := quic.Listen(conn, tlsConfig, quicConfig) + ln, err := quic.ListenEarly(conn, tlsConfigQUICALPN(tlsConfig), quicConfig) if err != nil { return nil, err } @@ -223,7 +197,7 @@ func QUICListener(addr string, config *QUICConfig) (Listener, error) { func (l *quicListener) listenLoop() { for { - session, err := l.ln.Accept() + session, err := l.ln.Accept(context.Background()) if err != nil { log.Log("[quic] accept:", err) l.errChan <- err @@ -234,15 +208,15 @@ func (l *quicListener) listenLoop() { } } -func (l *quicListener) sessionLoop(session quic.Session) { +func (l *quicListener) sessionLoop(session quic.Connection) { log.Logf("[quic] %s <-> %s", session.RemoteAddr(), session.LocalAddr()) defer log.Logf("[quic] %s >-< %s", session.RemoteAddr(), session.LocalAddr()) for { - stream, err := session.AcceptStream() + stream, err := session.AcceptStream(context.Background()) if err != nil { log.Log("[quic] accept stream:", err) - session.Close() + session.CloseWithError(quic.ApplicationErrorCode(0), "closed") return } @@ -291,12 +265,12 @@ func (c *quicConn) RemoteAddr() net.Addr { } type quicCipherConn struct { - *net.UDPConn + net.PacketConn key []byte } func (conn *quicCipherConn) ReadFrom(data []byte) (n int, addr net.Addr, err error) { - n, addr, err = conn.UDPConn.ReadFrom(data) + n, addr, err = conn.PacketConn.ReadFrom(data) if err != nil { return } @@ -316,7 +290,7 @@ func (conn *quicCipherConn) WriteTo(data []byte, addr net.Addr) (n int, err erro return } - _, err = conn.UDPConn.WriteTo(b, addr) + _, err = conn.PacketConn.WriteTo(b, addr) if err != nil { return } @@ -362,3 +336,13 @@ func (conn *quicCipherConn) decrypt(data []byte) ([]byte, error) { nonce, ciphertext := data[:nonceSize], data[nonceSize:] return gcm.Open(nil, nonce, ciphertext, nil) } + +func tlsConfigQUICALPN(tlsConfig *tls.Config) *tls.Config { + if tlsConfig == nil { + panic("quic: tlsconfig is nil") + } + tlsConfigQUIC := &tls.Config{} + *tlsConfigQUIC = *tlsConfig + tlsConfigQUIC.NextProtos = []string{"http/3", "quic/v1"} + return tlsConfigQUIC +} diff --git a/relay.go b/relay.go index c5d140b..74423f4 100644 --- a/relay.go +++ b/relay.go @@ -84,7 +84,7 @@ func (c *relayConnector) ConnectContext(ctx context.Context, conn net.Conn, netw atype = relay.AddrIPv4 } - req.Features = append(req.Features, &relay.TargetAddrFeature{ + req.Features = append(req.Features, &relay.AddrFeature{ AType: atype, Host: host, Port: uint16(nport), @@ -155,8 +155,8 @@ func (h *relayHandler) Handle(conn net.Conn) { feature := f.(*relay.UserAuthFeature) user, pass = feature.Username, feature.Password } - if f.Type() == relay.FeatureTargetAddr { - feature := f.(*relay.TargetAddrFeature) + if f.Type() == relay.FeatureAddr { + feature := f.(*relay.AddrFeature) raddr = net.JoinHostPort(feature.Host, strconv.Itoa(int(feature.Port))) } } diff --git a/resolver.go b/resolver.go index 618d724..69e659d 100644 --- a/resolver.go +++ b/resolver.go @@ -263,9 +263,7 @@ func (r *resolver) copyServers() []NameServer { defer r.mux.RUnlock() servers := make([]NameServer, len(r.servers)) - for i := range r.servers { - servers[i] = r.servers[i] - } + copy(servers, r.servers) return servers } @@ -312,17 +310,28 @@ func (r *resolver) resolve(ctx context.Context, ex Exchanger, host string) (ips r.mux.RUnlock() if prefer == "ipv6" { // prefer ipv6 - mq := &dns.Msg{} - mq.SetQuestion(dns.Fqdn(host), dns.TypeAAAA) - ips, err = r.resolveIPs(ctx, ex, mq) - if err != nil || len(ips) > 0 { + if ips, err = r.resolve6(ctx, ex, host); len(ips) > 0 { return } + return r.resolve4(ctx, ex, host) } - mq := &dns.Msg{} + if ips, err = r.resolve4(ctx, ex, host); len(ips) > 0 { + return + } + return r.resolve6(ctx, ex, host) +} + +func (r *resolver) resolve4(ctx context.Context, ex Exchanger, host string) (ips []net.IP, err error) { + mq := dns.Msg{} mq.SetQuestion(dns.Fqdn(host), dns.TypeA) - return r.resolveIPs(ctx, ex, mq) + return r.resolveIPs(ctx, ex, &mq) +} + +func (r *resolver) resolve6(ctx context.Context, ex Exchanger, host string) (ips []net.IP, err error) { + mq := dns.Msg{} + mq.SetQuestion(dns.Fqdn(host), dns.TypeAAAA) + return r.resolveIPs(ctx, ex, &mq) } func (r *resolver) resolveIPs(ctx context.Context, ex Exchanger, mq *dns.Msg) (ips []net.IP, err error) { @@ -709,7 +718,8 @@ func (ex *dnsExchanger) Exchange(ctx context.Context, query []byte) ([]byte, err defer c.Close() conn := &dns.Conn{ - Conn: c, + Conn: c, + UDPSize: 1024, } if _, err = conn.Write(query); err != nil { return nil, err diff --git a/selector.go b/selector.go index 12545ac..bff6d11 100644 --- a/selector.go +++ b/selector.go @@ -12,7 +12,7 @@ import ( var ( // ErrNoneAvailable indicates there is no node available. - ErrNoneAvailable = errors.New("none available") + ErrNoneAvailable = errors.New("none node available") ) // NodeSelector as a mechanism to pick nodes and mark their status. diff --git a/server.go b/server.go index dd8d556..a93d11d 100644 --- a/server.go +++ b/server.go @@ -112,11 +112,11 @@ func transport(rw1, rw2 io.ReadWriter) error { errc <- copyBuffer(rw2, rw1) }() - err := <-errc - if err != nil && err == io.EOF { - err = nil + if err := <-errc; err != nil && err != io.EOF { + return err } - return err + + return nil } func copyBuffer(dst io.Writer, src io.Reader) error { diff --git a/signal_unix.go b/signal_unix.go index f1e9140..469edce 100644 --- a/signal_unix.go +++ b/signal_unix.go @@ -1,3 +1,4 @@ +//go:build !windows // +build !windows package gost @@ -8,7 +9,7 @@ import ( "syscall" "github.com/go-log/log" - "github.com/xtaci/kcp-go" + "github.com/xtaci/kcp-go/v5" ) func kcpSigHandler() { diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml new file mode 100644 index 0000000..b438421 --- /dev/null +++ b/snap/snapcraft.yaml @@ -0,0 +1,34 @@ +name: gost +base: core20 +version: '2.11.5' +summary: A simple security tunnel written in golang +description: | + Project: https://github.com/ginuerzh/gost + Wiki: https://v2.gost.run +icon: gost.png +website: https://v2.gost.run +license: MIT + + +confinement: strict +grade: stable + +parts: + gost: + plugin: go + go-channel: latest/stable + source: https://github.com/ginuerzh/gost + source-subdir: cmd/gost + source-type: git + source-tag: v2.11.5 + build-packages: + - gcc + +apps: + gost: + command: bin/gost + plugs: + - home + - network + - network-bind + diff --git a/snapcraft.yaml b/snapcraft.yaml deleted file mode 100644 index f58b4e6..0000000 --- a/snapcraft.yaml +++ /dev/null @@ -1,43 +0,0 @@ -name: gost -type: app -version: '2.11.1' -title: GO Simple Tunnel -summary: A simple security tunnel written in golang -description: | - https://github.com/ginuerzh/gost -confinement: strict -grade: stable -base: core18 -license: MIT -parts: - gost: - plugin: nil - build-snaps: [go/1.13/stable] - source: https://github.com/ginuerzh/gost.git - source-subdir: cmd/gost - source-type: git - source-branch: '2' - build-packages: - - build-essential - override-build: | - set -ex - - echo "Starting override-build:" - pwd - cd $SNAPCRAFT_PART_BUILD - GO111MODULE=on CGO_ENABLED=0 go build --ldflags="-s -w" - ./gost -V - - echo "Installing to ${SNAPCRAFT_PART_INSTALL}..." - install -d $SNAPCRAFT_PART_INSTALL/bin - cp -v gost $SNAPCRAFT_PART_INSTALL/bin/ - - echo "Override-build done!" -apps: - gost: - command: bin/gost - plugs: - - home - - network - - network-bind - diff --git a/sni.go b/sni.go index e57d4a0..7d4c268 100644 --- a/sni.go +++ b/sni.go @@ -18,7 +18,7 @@ import ( "sync" "github.com/asaskevich/govalidator" - dissector "github.com/ginuerzh/tls-dissector" + dissector "github.com/go-gost/tls-dissector" "github.com/go-log/log" ) diff --git a/sockopts_linux.go b/sockopts_linux.go new file mode 100644 index 0000000..380f272 --- /dev/null +++ b/sockopts_linux.go @@ -0,0 +1,11 @@ +package gost + +import "syscall" + +func setSocketMark(fd int, value int) (e error) { + return syscall.SetsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_MARK, value) +} + +func setSocketInterface(fd int, value string) (e error) { + return syscall.SetsockoptString(fd, syscall.SOL_SOCKET, syscall.SO_BINDTODEVICE, value) +} \ No newline at end of file diff --git a/sockopts_other.go b/sockopts_other.go new file mode 100644 index 0000000..1f57c84 --- /dev/null +++ b/sockopts_other.go @@ -0,0 +1,12 @@ +//go:build !linux +// +build !linux + +package gost + +func setSocketMark(fd int, value int) (e error) { + return nil +} + +func setSocketInterface(fd int, value string) (e error) { + return nil +} diff --git a/socks.go b/socks.go index 7568205..dfd8012 100644 --- a/socks.go +++ b/socks.go @@ -10,11 +10,12 @@ import ( "net" "net/url" "strconv" + "strings" "sync" "time" - "github.com/ginuerzh/gosocks4" - "github.com/ginuerzh/gosocks5" + "github.com/go-gost/gosocks4" + "github.com/go-gost/gosocks5" "github.com/go-log/log" smux "github.com/xtaci/smux" ) @@ -1630,17 +1631,21 @@ func (h *socks5Handler) muxBindOn(conn net.Conn, addr string) { } } -// TODO: support ipv6 and domain +// TODO: support domain func toSocksAddr(addr net.Addr) *gosocks5.Addr { host := "0.0.0.0" port := 0 + addrType := gosocks5.AddrIPv4 if addr != nil { h, p, _ := net.SplitHostPort(addr.String()) host = h port, _ = strconv.Atoi(p) + if strings.Count(host, ":") > 0 { + addrType = gosocks5.AddrIPv6 + } } return &gosocks5.Addr{ - Type: gosocks5.AddrIPv4, + Type: addrType, Host: host, Port: uint16(port), } diff --git a/ss.go b/ss.go index e3532fd..052cf19 100644 --- a/ss.go +++ b/ss.go @@ -10,7 +10,7 @@ import ( "net/url" "time" - "github.com/ginuerzh/gosocks5" + "github.com/go-gost/gosocks5" "github.com/go-log/log" "github.com/shadowsocks/go-shadowsocks2/core" ss "github.com/shadowsocks/shadowsocks-go/shadowsocks" @@ -580,7 +580,7 @@ func (c *shadowCipher) StreamConn(conn net.Conn) net.Conn { } func (c *shadowCipher) PacketConn(conn net.PacketConn) net.PacketConn { - return ss.NewSecurePacketConn(conn, c.cipher.Copy(), false) + return ss.NewSecurePacketConn(conn, c.cipher.Copy()) } func initShadowCipher(info *url.Userinfo) (cipher core.Cipher) { diff --git a/tuntap_linux.go b/tuntap_linux.go index 20c609f..c63ffaa 100644 --- a/tuntap_linux.go +++ b/tuntap_linux.go @@ -3,15 +3,15 @@ package gost import ( "fmt" "net" + "os/exec" + "strings" - "github.com/docker/libcontainer/netlink" "github.com/go-log/log" - "github.com/milosgajdos/tenus" "github.com/songgao/water" ) func createTun(cfg TunConfig) (conn net.Conn, itf *net.Interface, err error) { - ip, ipNet, err := net.ParseCIDR(cfg.Addr) + ip, _, err := net.ParseCIDR(cfg.Addr) if err != nil { return } @@ -26,35 +26,21 @@ func createTun(cfg TunConfig) (conn net.Conn, itf *net.Interface, err error) { return } - link, err := tenus.NewLinkFrom(ifce.Name()) - if err != nil { - return - } - mtu := cfg.MTU if mtu <= 0 { mtu = DefaultMTU } - cmd := fmt.Sprintf("ip link set dev %s mtu %d", ifce.Name(), mtu) - log.Log("[tun]", cmd) - if er := link.SetLinkMTU(mtu); er != nil { - err = fmt.Errorf("%s: %v", cmd, er) - return + if err = exeCmd(fmt.Sprintf("ip link set dev %s mtu %d", ifce.Name(), mtu)); err != nil { + log.Log(err) } - cmd = fmt.Sprintf("ip address add %s dev %s", cfg.Addr, ifce.Name()) - log.Log("[tun]", cmd) - if er := link.SetLinkIp(ip, ipNet); er != nil { - err = fmt.Errorf("%s: %v", cmd, er) - return + if err = exeCmd(fmt.Sprintf("ip address add %s dev %s", cfg.Addr, ifce.Name())); err != nil { + log.Log(err) } - cmd = fmt.Sprintf("ip link set dev %s up", ifce.Name()) - log.Log("[tun]", cmd) - if er := link.SetLinkUp(); er != nil { - err = fmt.Errorf("%s: %v", cmd, er) - return + if err = exeCmd(fmt.Sprintf("ip link set dev %s up", ifce.Name())); err != nil { + log.Log(err) } if err = addTunRoutes(ifce.Name(), cfg.Routes...); err != nil { @@ -75,9 +61,8 @@ func createTun(cfg TunConfig) (conn net.Conn, itf *net.Interface, err error) { func createTap(cfg TapConfig) (conn net.Conn, itf *net.Interface, err error) { var ip net.IP - var ipNet *net.IPNet if cfg.Addr != "" { - ip, ipNet, err = net.ParseCIDR(cfg.Addr) + ip, _, err = net.ParseCIDR(cfg.Addr) if err != nil { return } @@ -93,37 +78,23 @@ func createTap(cfg TapConfig) (conn net.Conn, itf *net.Interface, err error) { return } - link, err := tenus.NewLinkFrom(ifce.Name()) - if err != nil { - return - } - mtu := cfg.MTU if mtu <= 0 { mtu = DefaultMTU } - cmd := fmt.Sprintf("ip link set dev %s mtu %d", ifce.Name(), mtu) - log.Log("[tap]", cmd) - if er := link.SetLinkMTU(mtu); er != nil { - err = fmt.Errorf("%s: %v", cmd, er) - return + if err = exeCmd(fmt.Sprintf("ip link set dev %s mtu %d", ifce.Name(), mtu)); err != nil { + log.Log(err) } if cfg.Addr != "" { - cmd = fmt.Sprintf("ip address add %s dev %s", cfg.Addr, ifce.Name()) - log.Log("[tap]", cmd) - if er := link.SetLinkIp(ip, ipNet); er != nil { - err = fmt.Errorf("%s: %v", cmd, er) - return + if err = exeCmd(fmt.Sprintf("ip address add %s dev %s", cfg.Addr, ifce.Name())); err != nil { + log.Log(err) } } - cmd = fmt.Sprintf("ip link set dev %s up", ifce.Name()) - log.Log("[tap]", cmd) - if er := link.SetLinkUp(); er != nil { - err = fmt.Errorf("%s: %v", cmd, er) - return + if err = exeCmd(fmt.Sprintf("ip link set dev %s up", ifce.Name())); err != nil { + log.Log(err) } if err = addTapRoutes(ifce.Name(), cfg.Gateway, cfg.Routes...); err != nil { @@ -149,8 +120,10 @@ func addTunRoutes(ifName string, routes ...IPRoute) error { } cmd := fmt.Sprintf("ip route add %s dev %s", route.Dest.String(), ifName) log.Logf("[tun] %s", cmd) - if err := netlink.AddRoute(route.Dest.String(), "", "", ifName); err != nil { - return fmt.Errorf("%s: %v", cmd, err) + + args := strings.Split(cmd, " ") + if er := exec.Command(args[0], args[1:]...).Run(); er != nil { + log.Logf("[tun] %s: %v", cmd, er) } } return nil @@ -163,9 +136,22 @@ func addTapRoutes(ifName string, gw string, routes ...string) error { } cmd := fmt.Sprintf("ip route add %s via %s dev %s", route, gw, ifName) log.Logf("[tap] %s", cmd) - if err := netlink.AddRoute(route, "", gw, ifName); err != nil { - return fmt.Errorf("%s: %v", cmd, err) + + args := strings.Split(cmd, " ") + if er := exec.Command(args[0], args[1:]...).Run(); er != nil { + log.Logf("[tap] %s: %v", cmd, er) } } return nil } + +func exeCmd(cmd string) error { + log.Log(cmd) + + args := strings.Split(cmd, " ") + if err := exec.Command(args[0], args[1:]...).Run(); err != nil { + return fmt.Errorf("%s: %v", cmd, err) + } + + return nil +} diff --git a/tuntap_windows.go b/tuntap_windows.go index 21af512..dd467aa 100644 --- a/tuntap_windows.go +++ b/tuntap_windows.go @@ -28,7 +28,7 @@ func createTun(cfg TunConfig) (conn net.Conn, itf *net.Interface, err error) { return } - cmd := fmt.Sprintf("netsh interface ip set address name=%s "+ + cmd := fmt.Sprintf("netsh interface ip set address name=\"%s\" "+ "source=static addr=%s mask=%s gateway=none", ifce.Name(), ip.String(), ipMask(ipNet.Mask)) log.Log("[tun]", cmd) @@ -70,7 +70,7 @@ func createTap(cfg TapConfig) (conn net.Conn, itf *net.Interface, err error) { } if ip != nil && ipNet != nil { - cmd := fmt.Sprintf("netsh interface ip set address name=%s "+ + cmd := fmt.Sprintf("netsh interface ip set address name=\"%s\" "+ "source=static addr=%s mask=%s gateway=none", ifce.Name(), ip.String(), ipMask(ipNet.Mask)) log.Log("[tap]", cmd) @@ -105,7 +105,7 @@ func addTunRoutes(ifName string, gw string, routes ...IPRoute) error { deleteRoute(ifName, route.Dest.String()) - cmd := fmt.Sprintf("netsh interface ip add route prefix=%s interface=%s store=active", + cmd := fmt.Sprintf("netsh interface ip add route prefix=%s interface=\"%s\" store=active", route.Dest.String(), ifName) if gw != "" { cmd += " nexthop=" + gw @@ -127,7 +127,7 @@ func addTapRoutes(ifName string, gw string, routes ...string) error { deleteRoute(ifName, route) - cmd := fmt.Sprintf("netsh interface ip add route prefix=%s interface=%s store=active", + cmd := fmt.Sprintf("netsh interface ip add route prefix=%s interface=\"%s\" store=active", route, ifName) if gw != "" { cmd += " nexthop=" + gw @@ -142,7 +142,7 @@ func addTapRoutes(ifName string, gw string, routes ...string) error { } func deleteRoute(ifName string, route string) error { - cmd := fmt.Sprintf("netsh interface ip delete route prefix=%s interface=%s store=active", + cmd := fmt.Sprintf("netsh interface ip delete route prefix=%s interface=\"%s\" store=active", route, ifName) args := strings.Split(cmd, " ") return exec.Command(args[0], args[1:]...).Run()