diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 71ee23e..dd172d9 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -6,17 +6,18 @@ on: pull_request: branches: - '**' + workflow_dispatch: jobs: windowsAmd64Build: name: Build Windows amd64 Version runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Setting up Go - uses: actions/setup-go@v2 + uses: actions/setup-go@v5 with: - go-version: "1.20" + go-version: "1.21" - name: Building Windows amd64 Version run: | CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build -o WireProxy_amd64.exe -v ./cmd/wireproxy @@ -24,7 +25,7 @@ jobs: mv WireProxy_amd64.exe wireproxy.exe cp wireproxy.exe release_windows_amd64/wireproxy.exe - name: Upload Windows amd64 Version - uses: actions/upload-artifact@v1 + uses: actions/upload-artifact@v4 with: name: WireProxy_windows_amd64 path: release_windows_amd64 @@ -32,11 +33,11 @@ jobs: name: Build Windows arm64 Version runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Setting up Go - uses: actions/setup-go@v2 + uses: actions/setup-go@v5 with: - go-version: "1.20" + go-version: "1.21" - name: Building Windows arm64 Version run: | CGO_ENABLED=0 GOOS=windows GOARCH=arm64 go build -o WireProxy_arm64.exe -v ./cmd/wireproxy @@ -44,7 +45,7 @@ jobs: mv WireProxy_arm64.exe wireproxy.exe cp wireproxy.exe release_windows_arm64/wireproxy.exe - name: Upload Windows arm64 Version - uses: actions/upload-artifact@v1 + uses: actions/upload-artifact@v4 with: name: WireProxy_windows_arm64 path: release_windows_arm64 @@ -52,11 +53,11 @@ jobs: name: Build Linux amd64 Version runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Setting up Go - uses: actions/setup-go@v2 + uses: actions/setup-go@v5 with: - go-version: "1.20" + go-version: "1.21" - name: Building Linux amd64 Version run: | CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o WireProxy_amd64 -v ./cmd/wireproxy @@ -64,7 +65,7 @@ jobs: mv WireProxy_amd64 wireproxy cp wireproxy release_linux_amd64/wireproxy - name: Upload Linux amd64 Version - uses: actions/upload-artifact@v1 + uses: actions/upload-artifact@v4 with: name: WireProxy_linux_amd64 path: release_linux_amd64 @@ -72,11 +73,11 @@ jobs: name: Build Linux arm64 Version runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Setting up Go - uses: actions/setup-go@v2 + uses: actions/setup-go@v5 with: - go-version: "1.20" + go-version: "1.21" - name: Building Linux arm64 Version run: | CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -o WireProxy_arm64 -v ./cmd/wireproxy @@ -84,7 +85,7 @@ jobs: mv WireProxy_arm64 wireproxy cp wireproxy release_linux_arm64/wireproxy - name: Upload Linux arm64 Version - uses: actions/upload-artifact@v1 + uses: actions/upload-artifact@v4 with: name: WireProxy_linux_arm64 path: release_linux_arm64 @@ -92,11 +93,11 @@ jobs: name: Build Linux s390x Version runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Setting up Go - uses: actions/setup-go@v2 + uses: actions/setup-go@v5 with: - go-version: "1.20" + go-version: "1.21" - name: Building Linux s390x Version run: | CGO_ENABLED=0 GOOS=linux GOARCH=s390x go build -o WireProxy_s390x -v ./cmd/wireproxy @@ -104,7 +105,7 @@ jobs: mv WireProxy_s390x wireproxy cp wireproxy release_linux_s390x/wireproxy - name: Upload Linux s390x Version - uses: actions/upload-artifact@v1 + uses: actions/upload-artifact@v4 with: name: WireProxy_linux_s390x path: release_linux_s390x @@ -112,11 +113,11 @@ jobs: name: Build Darwin amd64 Version runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Setting up Go - uses: actions/setup-go@v2 + uses: actions/setup-go@v5 with: - go-version: "1.20" + go-version: "1.21" - name: Building Darwin amd64 Version run: | CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -o WireProxy_amd64 -v ./cmd/wireproxy @@ -124,7 +125,7 @@ jobs: mv WireProxy_amd64 wireproxy cp wireproxy release_darwin_amd64/wireproxy - name: Upload Darwin amd64 Version - uses: actions/upload-artifact@v1 + uses: actions/upload-artifact@v4 with: name: WireProxy_darwin_amd64 path: release_darwin_amd64 @@ -132,11 +133,11 @@ jobs: name: Build Darwin arm64 Version runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Setting up Go - uses: actions/setup-go@v2 + uses: actions/setup-go@v5 with: - go-version: "1.20" + go-version: "1.21" - name: Building Darwin arm64 Version run: | CGO_ENABLED=0 GOOS=darwin GOARCH=arm64 go build -o WireProxy_arm64 -v ./cmd/wireproxy @@ -144,7 +145,7 @@ jobs: mv WireProxy_arm64 wireproxy cp wireproxy release_darwin_arm64/wireproxy - name: Upload Darwin arm64 Version - uses: actions/upload-artifact@v1 + uses: actions/upload-artifact@v4 with: name: WireProxy_darwin_arm64 path: release_darwin_arm64 diff --git a/.github/workflows/container.yml b/.github/workflows/container.yml index 3600a36..b965173 100644 --- a/.github/workflows/container.yml +++ b/.github/workflows/container.yml @@ -28,26 +28,26 @@ jobs: steps: - name: Set up QEMU - uses: docker/setup-qemu-action@v2 + uses: docker/setup-qemu-action@v3 - name: Set up Docker Buildx id: buildx - uses: docker/setup-buildx-action@v2.0.0 + uses: docker/setup-buildx-action@v3.0.0 - name: Login to GitHub Container Registry - uses: docker/login-action@v2 + uses: docker/login-action@v3 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: recursive # Needed for buildx gha cache to work - name: Expose GitHub Runtime - uses: crazy-max/ghaction-github-runtime@v2 + uses: crazy-max/ghaction-github-runtime@v3 - name: Build container env: diff --git a/.github/workflows/golangci-lint.yml b/.github/workflows/golangci-lint.yml index 3b60df1..6fb237f 100644 --- a/.github/workflows/golangci-lint.yml +++ b/.github/workflows/golangci-lint.yml @@ -6,6 +6,8 @@ on: pull_request: branches: - '**' + workflow_dispatch: + permissions: contents: read jobs: @@ -13,9 +15,11 @@ jobs: name: lint runs-on: ubuntu-latest steps: - - uses: actions/setup-go@v2 + - uses: actions/setup-go@v5 with: - go-version: '1.20' - - uses: actions/checkout@v3 + go-version: '1.21' + - uses: actions/checkout@v4 - name: golangci-lint - uses: golangci/golangci-lint-action@v3 + uses: golangci/golangci-lint-action@v4 + with: + version: latest \ No newline at end of file diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e3aff57..6f5dbb8 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -6,17 +6,18 @@ on: pull_request: branches: - '**' + workflow_dispatch: jobs: test: name: Test wireproxy runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Setting up Go - uses: actions/setup-go@v2 + uses: actions/setup-go@v5 with: - go-version: "1.20" + go-version: "1.21" - name: Install dependencies run: sudo apt install wireguard curl - name: Building wireproxy diff --git a/.github/workflows/wireproxy.yml b/.github/workflows/wireproxy.yml index 7ba2d55..17cc191 100644 --- a/.github/workflows/wireproxy.yml +++ b/.github/workflows/wireproxy.yml @@ -28,17 +28,17 @@ jobs: cp ./.github/wireproxy-releaser.yml ${{ env.workdir }}/.goreleaser.yml - name: Set up GoReleaser - uses: actions/setup-go@v2 + uses: actions/setup-go@v5 with: - go-version: "1.20" + go-version: "1.21" - name: Run GoReleaser - uses: goreleaser/goreleaser-action@v2 + uses: goreleaser/goreleaser-action@v5 with: distribution: goreleaser workdir: ${{ env.workdir }} version: latest - args: release --rm-dist + args: release --clean env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/Dockerfile b/Dockerfile index a054779..9906d1c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ # Start by building the application. -FROM docker.io/golang:1.20 as build +FROM docker.io/golang:1.21 as build WORKDIR /usr/src/wireproxy COPY . . @@ -14,6 +14,6 @@ VOLUME [ "/etc/wireproxy"] ENTRYPOINT [ "/usr/bin/wireproxy" ] CMD [ "--config", "/etc/wireproxy/config" ] -LABEL org.opencontainers.image.title wireproxy -LABEL org.opencontainers.image.description "Wireguard client that exposes itself as a socks5 proxy" -LABEL org.opencontainers.image.licenses ISC +LABEL org.opencontainers.image.title="wireproxy" +LABEL org.opencontainers.image.description="Wireguard client that exposes itself as a socks5 proxy" +LABEL org.opencontainers.image.licenses="ISC" diff --git a/cmd/wireproxy/main.go b/cmd/wireproxy/main.go index 9cc4874..f6c5796 100644 --- a/cmd/wireproxy/main.go +++ b/cmd/wireproxy/main.go @@ -1,14 +1,16 @@ package main import ( + "context" "fmt" "log" "os" "os/exec" + "os/signal" "syscall" "github.com/akamensky/argparse" - "github.com/octeep/wireproxy" + "github.com/pufferffish/wireproxy" "golang.zx2c4.com/wireguard/device" "suah.dev/protect" ) @@ -46,6 +48,15 @@ func executablePath() string { } func main() { + s := make(chan os.Signal, 1) + signal.Notify(s, syscall.SIGINT, syscall.SIGQUIT) + ctx, cancel := context.WithCancel(context.Background()) + + go func() { + <-s + cancel() + }() + exePath := executablePath() unveilOrPanic("/", "r") unveilOrPanic(exePath, "x") @@ -138,5 +149,5 @@ func main() { go spawner.SpawnRoutine(tnet) } - select {} // sleep eternally + <-ctx.Done() } diff --git a/config.go b/config.go index 1a6e7c2..4f363ec 100644 --- a/config.go +++ b/config.go @@ -36,7 +36,7 @@ type TCPClientTunnelConfig struct { } type STDIOTunnelConfig struct { - Target string + Target string } type TCPServerTunnelConfig struct { @@ -125,8 +125,9 @@ func parseNetIP(section *ini.Section, keyName string) ([]netip.Addr, error) { return []netip.Addr{}, nil } - var ips []netip.Addr - for _, str := range key.StringsWithShadows(",") { + keys := key.StringsWithShadows(",") + var ips = make([]netip.Addr, 0, len(keys)) + for _, str := range keys { str = strings.TrimSpace(str) ip, err := netip.ParseAddr(str) if err != nil { @@ -143,8 +144,9 @@ func parseCIDRNetIP(section *ini.Section, keyName string) ([]netip.Addr, error) return []netip.Addr{}, nil } - var ips []netip.Addr - for _, str := range key.StringsWithShadows(",") { + keys := key.StringsWithShadows(",") + var ips = make([]netip.Addr, 0, len(keys)) + for _, str := range keys { prefix, err := netip.ParsePrefix(str) if err != nil { return nil, err @@ -162,8 +164,9 @@ func parseAllowedIPs(section *ini.Section) ([]netip.Prefix, error) { return []netip.Prefix{}, nil } - var ips []netip.Prefix - for _, str := range key.StringsWithShadows(",") { + keys := key.StringsWithShadows(",") + var ips = make([]netip.Prefix, 0, len(keys)) + for _, str := range keys { prefix, err := netip.ParsePrefix(str) if err != nil { return nil, err @@ -237,7 +240,7 @@ func ParseInterface(cfg *ini.File, device *DeviceConfig) error { return nil } -// ParsePeer parses the [Peer] section and extract the information into `peers` +// ParsePeers parses the [Peer] section and extract the information into `peers` func ParsePeers(cfg *ini.File, peers *[]PeerConfig) error { sections, err := cfg.SectionsByName("Peer") if len(sections) < 1 || err != nil { diff --git a/go.mod b/go.mod index 162deac..ab52783 100644 --- a/go.mod +++ b/go.mod @@ -1,23 +1,25 @@ -module github.com/octeep/wireproxy +module github.com/pufferffish/wireproxy -go 1.18 +go 1.21.1 + +toolchain go1.21.6 require ( github.com/MakeNowJust/heredoc/v2 v2.0.1 - github.com/akamensky/argparse v1.3.1 - github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 + github.com/akamensky/argparse v1.4.0 github.com/go-ini/ini v1.67.0 - golang.zx2c4.com/wireguard v0.0.0-20231010133717-42ec952eadc2 - suah.dev/protect v1.2.0 + github.com/things-go/go-socks5 v0.0.5 + golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173 + suah.dev/protect v1.2.3 ) require ( github.com/google/btree v1.1.2 // indirect - github.com/stretchr/testify v1.8.0 // indirect - golang.org/x/crypto v0.17.0 // indirect - golang.org/x/net v0.17.0 // indirect - golang.org/x/sys v0.15.0 // indirect - golang.org/x/time v0.3.0 // indirect + github.com/sourcegraph/conc v0.3.0 // indirect + golang.org/x/crypto v0.19.0 // indirect + golang.org/x/net v0.21.0 // indirect + golang.org/x/sys v0.17.0 // indirect + golang.org/x/time v0.5.0 // indirect golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect gvisor.dev/gvisor v0.0.0-20230927004350-cbd86285d259 // indirect ) diff --git a/go.sum b/go.sum index fc37fde..949c441 100644 --- a/go.sum +++ b/go.sum @@ -1,10 +1,7 @@ github.com/MakeNowJust/heredoc/v2 v2.0.1 h1:rlCHh70XXXv7toz95ajQWOWQnN4WNLt0TdpZYIR/J6A= github.com/MakeNowJust/heredoc/v2 v2.0.1/go.mod h1:6/2Abh5s+hc3g9nbWLe9ObDIOhaRrqsyY9MWy+4JdRM= -github.com/akamensky/argparse v1.3.1 h1:kP6+OyvR0fuBH6UhbE6yh/nskrDEIQgEA1SUXDPjx4g= -github.com/akamensky/argparse v1.3.1/go.mod h1:S5kwC7IuDcEr5VeXtGPRVZ5o/FdhcMlQz4IZQuw64xA= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/akamensky/argparse v1.4.0 h1:YGzvsTqCvbEZhL8zZu2AiA5nq805NZh75JNj4ajn1xc= +github.com/akamensky/argparse v1.4.0/go.mod h1:S5kwC7IuDcEr5VeXtGPRVZ5o/FdhcMlQz4IZQuw64xA= 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/go-ini/ini v1.67.0 h1:z6ZrTEZqSWOTyH2FlglNbNgARyHG8oLW9gMELqKr06A= @@ -13,29 +10,28 @@ github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU= github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= 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/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= -golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= -golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= -golang.org/x/sys v0.0.0-20210917161153-d61c044b1678/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= -golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= -golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= +github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/things-go/go-socks5 v0.0.5 h1:qvKaGcBkfDrUL33SchHN93srAmYGzb4CxSM2DPYufe8= +github.com/things-go/go-socks5 v0.0.5/go.mod h1:mtzInf8v5xmsBpHZVbIw2YQYhc4K0jRwzfsH64Uh0IQ= +golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo= +golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= +golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 h1:B82qJJgjvYKsXS9jeunTOisW56dUokqW/FOteYJJ/yg= golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI= -golang.zx2c4.com/wireguard v0.0.0-20231010133717-42ec952eadc2 h1:I9wdPjBlr0efFqY7IHryfOXBdTxA4j8F0ynd227sYVU= -golang.zx2c4.com/wireguard v0.0.0-20231010133717-42ec952eadc2/go.mod h1:tkCQ4FQXmpAgYVh++1cq16/dH4QJtmvpRv19DWGAHSA= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173 h1:/jFs0duh4rdb8uIfPMv78iAJGcPKDeqAFnaLBropIC4= +golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173/go.mod h1:tkCQ4FQXmpAgYVh++1cq16/dH4QJtmvpRv19DWGAHSA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gvisor.dev/gvisor v0.0.0-20230927004350-cbd86285d259 h1:TbRPT0HtzFP3Cno1zZo7yPzEEnfu8EjLfl6IU9VfqkQ= gvisor.dev/gvisor v0.0.0-20230927004350-cbd86285d259/go.mod h1:AVgIgHMwK63XvmAzWG9vLQ41YnVHN0du0tEC46fI7yY= -suah.dev/protect v1.2.0 h1:4G4V43yVYXCjLFzaE9QJR0fLo3rf5vNBS9YxyoI19DU= -suah.dev/protect v1.2.0/go.mod h1:Ocn1yqUskqe/is6N2bxQxtT+fegbvQsOFyHbJAQu9XE= +suah.dev/protect v1.2.3 h1:aHeoNwZ9YPp64hrYaN0g0djNE1eRujgH63CrfRrUKdc= +suah.dev/protect v1.2.3/go.mod h1:n1R3XIbsnryKX7C1PO88i5Wgo0v8OTXm9K9FIKt4rfs= diff --git a/http.go b/http.go index fcdab44..9fa7932 100644 --- a/http.go +++ b/http.go @@ -10,6 +10,8 @@ import ( "net" "net/http" "strings" + + "github.com/sourcegraph/conc" ) const proxyAuthHeaderKey = "Proxy-Authorization" @@ -62,7 +64,7 @@ func (s *HTTPServer) handleConn(req *http.Request, conn net.Conn) (peer net.Conn _, err = conn.Write([]byte("HTTP/1.1 200 Connection established\r\n\r\n")) if err != nil { - peer.Close() + _ = peer.Close() peer = nil } @@ -83,7 +85,7 @@ func (s *HTTPServer) handle(req *http.Request) (peer net.Conn, err error) { err = req.Write(peer) if err != nil { - peer.Close() + _ = peer.Close() peer = nil return peer, fmt.Errorf("conn write failed: %w", err) } @@ -91,19 +93,19 @@ func (s *HTTPServer) handle(req *http.Request) (peer net.Conn, err error) { return } -func (s *HTTPServer) serve(conn net.Conn) error { - defer conn.Close() - - var rd io.Reader = bufio.NewReader(conn) - req, err := http.ReadRequest(rd.(*bufio.Reader)) +func (s *HTTPServer) serve(conn net.Conn) { + var rd = bufio.NewReader(conn) + req, err := http.ReadRequest(rd) if err != nil { - return fmt.Errorf("read request failed: %w", err) + log.Printf("read request failed: %s\n", err) + return } code, err := s.authenticate(req) if err != nil { _ = responseWith(req, code).Write(conn) - return err + log.Println(err) + return } var peer net.Conn @@ -114,43 +116,47 @@ func (s *HTTPServer) serve(conn net.Conn) error { peer, err = s.handle(req) default: _ = responseWith(req, http.StatusMethodNotAllowed).Write(conn) - return fmt.Errorf("unsupported protocol: %s", req.Method) + log.Printf("unsupported protocol: %s\n", req.Method) + return } if err != nil { - return fmt.Errorf("dial proxy failed: %w", err) + log.Printf("dial proxy failed: %s\n", err) + return } if peer == nil { - return fmt.Errorf("dial proxy failed: peer nil") + log.Println("dial proxy failed: peer nil") + return } - defer peer.Close() - go func() { - defer peer.Close() - defer conn.Close() - _, _ = io.Copy(conn, peer) + wg := conc.NewWaitGroup() + wg.Go(func() { + _, err = io.Copy(conn, peer) + _ = conn.Close() + }) + wg.Go(func() { + _, err = io.Copy(peer, conn) + _ = peer.Close() + }) + wg.Wait() }() - _, err = io.Copy(peer, conn) - - return err } // ListenAndServe is used to create a listener and serve on it func (s *HTTPServer) ListenAndServe(network, addr string) error { - server, err := net.Listen("tcp", s.config.BindAddress) + server, err := net.Listen(network, addr) if err != nil { return fmt.Errorf("listen tcp failed: %w", err) } - + defer func(server net.Listener) { + _ = server.Close() + }(server) for { conn, err := server.Accept() if err != nil { return fmt.Errorf("accept request failed: %w", err) } go func(conn net.Conn) { - err = s.serve(conn) - if err != nil { - log.Println(err) - } + s.serve(conn) }(conn) } } diff --git a/routine.go b/routine.go index 6bbba96..13fa944 100644 --- a/routine.go +++ b/routine.go @@ -11,10 +11,13 @@ import ( "os" "strconv" - "github.com/armon/go-socks5" + "github.com/sourcegraph/conc" + "github.com/things-go/go-socks5" + "github.com/things-go/go-socks5/bufferpool" - "golang.zx2c4.com/wireguard/tun/netstack" "net/netip" + + "golang.zx2c4.com/wireguard/tun/netstack" ) // errorLogger is the logger to print error message @@ -47,9 +50,8 @@ type addressPort struct { func (d VirtualTun) LookupAddr(ctx context.Context, name string) ([]string, error) { if d.SystemDNS { return net.DefaultResolver.LookupHost(ctx, name) - } else { - return d.Tnet.LookupContextHost(ctx, name) } + return d.Tnet.LookupContextHost(ctx, name) } // ResolveAddrWithContext resolves a hostname and returns an AddrPort. @@ -121,17 +123,24 @@ func (d VirtualTun) resolveToAddrPort(endpoint *addressPort) (*netip.AddrPort, e // SpawnRoutine spawns a socks5 server. func (config *Socks5Config) SpawnRoutine(vt *VirtualTun) { - conf := &socks5.Config{Dial: vt.Tnet.DialContext, Resolver: vt} + var authMethods []socks5.Authenticator if username := config.Username; username != "" { - validator := CredentialValidator{username: username} - validator.password = config.Password - conf.Credentials = validator + authMethods = append(authMethods, socks5.UserPassAuthenticator{ + Credentials: socks5.StaticCredentials{username: config.Password}, + }) + } else { + authMethods = append(authMethods, socks5.NoAuthAuthenticator{}) } - server, err := socks5.New(conf) - if err != nil { - log.Fatal(err) + + options := []socks5.Option{ + socks5.WithDial(vt.Tnet.DialContext), + socks5.WithResolver(vt), + socks5.WithAuthMethods(authMethods), + socks5.WithBufferPool(bufferpool.NewPool(256 * 1024)), } + server := socks5.NewServer(options...) + if err := server.ListenAndServe("tcp", config.BindAddress); err != nil { log.Fatal(err) } @@ -161,14 +170,12 @@ func (c CredentialValidator) Valid(username, password string) bool { return u&p == 1 } -// connForward copy data from `from` to `to`, then close both stream. +// connForward copy data from `from` to `to` func connForward(from io.ReadWriteCloser, to io.ReadWriteCloser) { _, err := io.Copy(to, from) if err != nil { errorLogger.Printf("Cannot forward traffic: %s\n", err.Error()) } - _ = from.Close() - _ = to.Close() } // tcpClientForward starts a new connection via wireguard and forward traffic from `conn` @@ -187,8 +194,20 @@ func tcpClientForward(vt *VirtualTun, raddr *addressPort, conn net.Conn) { return } - go connForward(sconn, conn) - go connForward(conn, sconn) + go func() { + wg := conc.NewWaitGroup() + wg.Go(func() { + connForward(sconn, conn) + }) + wg.Go(func() { + connForward(conn, sconn) + }) + wg.Wait() + _ = sconn.Close() + _ = conn.Close() + sconn = nil + conn = nil + }() } // STDIOTcpForward starts a new connection via wireguard and forward traffic from `conn` @@ -213,8 +232,18 @@ func STDIOTcpForward(vt *VirtualTun, raddr *addressPort) { return } - go connForward(os.Stdin, sconn) - go connForward(sconn, stdout) + go func() { + wg := conc.NewWaitGroup() + wg.Go(func() { + connForward(os.Stdin, sconn) + }) + wg.Go(func() { + connForward(sconn, stdout) + }) + wg.Wait() + _ = sconn.Close() + sconn = nil + }() } // SpawnRoutine spawns a local TCP server which acts as a proxy to the specified target @@ -264,8 +293,20 @@ func tcpServerForward(vt *VirtualTun, raddr *addressPort, conn net.Conn) { return } - go connForward(sconn, conn) - go connForward(conn, sconn) + go func() { + gr := conc.NewWaitGroup() + gr.Go(func() { + connForward(sconn, conn) + }) + gr.Go(func() { + connForward(conn, sconn) + }) + gr.Wait() + _ = sconn.Close() + _ = conn.Close() + sconn = nil + conn = nil + }() } // SpawnRoutine spawns a TCP server on wireguard which acts as a proxy to the specified target