Compare commits

...
71 Commits
Author SHA1 Message Date
xjasonlyu 9cbc99e8f5 Chore: bump golang.org/x/sys to v0.7.0 2023-04-06 12:54:12 +08:00
xjasonlyu 2dbd2caaa9 Fix: netstats JSON response 2023-04-03 19:59:37 +08:00
2d0bd1d219 Improve: tunnel/tcp pipe (#219)
Co-authored-by: xjasonlyu <xjasonlyu@gmail.com>
2023-04-03 19:15:24 +08:00
xjasonlyu 61a9d26815 Minor: UDP unidirectionalPacketStream 2023-04-03 19:13:03 +08:00
xjasonlyu 4cc02c822c Minor: improve tunnel/udp 2023-04-03 18:43:02 +08:00
xjasonlyu 20499c6432 Revert: cli tcp-wait-timeout option
This reverts commit 2c51a65685.
2023-04-03 17:57:13 +08:00
xjasonlyu ad522ebb35 Chore: minor renames 2023-04-03 17:43:19 +08:00
xjasonlyu 06d8bee2af Ignore: (*gonet.TCPConn).RemoteAddr() warning 2023-04-03 13:52:28 +08:00
xjasonlyu b809f89411 Revert: udp-rlybuf option
As a low-level networking tool, tun2socks should be able to handle UDP packets of all possible sizes. This reverts commit fb9ca95909.
2023-04-03 12:24:07 +08:00
xjasonlyu b8ff1859c1 Chore: update go mods 2023-04-02 20:20:56 +08:00
xjasonlyu 89c37dc156 Improve: deprecate isIgnorable
All errors should be returned by copyBuffer and handled by higher level functions.
2023-04-02 16:43:55 +08:00
xjasonlyu 1b8e063485 Fix: log message typo 2023-03-30 18:11:08 +08:00
xjasonlyu 195290884c Fix: potential crash by bad UDP address (#238) 2023-03-30 14:11:43 +08:00
xjasonlyu 3b343600e7 Chore: core loglevel to debug 2023-03-29 23:19:08 +08:00
2c51a65685 Feature: cli tcp-wait-timeout option (#156)
Co-authored-by: xjasonlyu <xjasonlyu@gmail.com>
2023-03-29 17:41:01 +08:00
xjasonlyu fb9ca95909 Feature: add udp-rlybuf option
* Default UDP relay buffer size: 16KiB
2023-03-29 16:56:03 +08:00
xjasonlyu 1e99f2d580 Chore: debug level log 2023-03-28 18:04:46 +08:00
xjasonlyu ce15b1b2c2 Improve: with default tracker 2023-03-28 18:00:05 +08:00
xjasonlyu c036db2e23 Chore: rm unused code 2023-03-27 19:11:56 +08:00
007c97fe67 Feature: support pre&post-up exec (#233)
* Add tun pre/post script
* Improve: pre & post tun

---------

Co-authored-by: xjasonlyu <xjasonlyu@gmail.com>
2023-03-27 13:26:39 +08:00
xjasonlyu 7327f2c784 Improve: with gvisor internal log 2023-03-27 13:21:10 +08:00
xjasonlyu 66860d3de8 Improve: enhance error handling 2023-03-27 00:43:39 +08:00
xjasonlyu c61d7b5a20 Chore: error is ignorable 2023-03-26 23:07:13 +08:00
xjasonlyu 680feede3b Improve: add tun io lock 2023-03-26 22:56:01 +08:00
xjasonlyu 22b15f6fab Improve: redirect stack log 2023-03-26 22:48:28 +08:00
xjasonlyu f7b4f75ed4 Fix: align with wireguard io 2023-03-26 22:10:21 +08:00
xjasonlyu 29feac8cd4 Chore: bump go mods 2023-03-26 14:40:39 +08:00
xjasonlyu 6cfc25309e Fix: rand linter
`math/rand.Read` has been deprecated since Go 1.20
2023-02-21 15:06:05 +08:00
xjasonlyu 1f63b239c3 Chore: update linter 2023-02-21 14:55:01 +08:00
xjasonlyu 041bc510ea Chore: bump go modules 2023-02-21 14:05:25 +08:00
xjasonlyu 51d8a27289 Chore: bump gvisor
v0.0.0-20230219185229-4f1045309c43
2023-02-21 14:03:17 +08:00
xjasonlyu 5ffb0186bf Improve: do not stale labeled issues 2023-02-12 14:04:35 +08:00
xjasonlyu 8a2e5cebeb Fix: deprecate rand.Seed 2023-02-06 15:39:37 +08:00
xjasonlyu 846d3d87a7 Chore: bump go.mod to 1.20 2023-02-06 15:39:15 +08:00
xjasonlyu b491e17bfa Chore: add v2 to prefix 2023-02-06 15:38:46 +08:00
xjasonlyu fbe4c22347 Revert: undo crypto/rand
This reverts commit 4a8bf64cb1.
2023-02-06 15:31:05 +08:00
xjasonlyu 4a8bf64cb1 Improve: use crypto/rand 2023-02-04 14:26:41 +08:00
xjasonlyu 059f661862 Chore: bump to go1.20 2023-02-04 13:52:29 +08:00
xjasonlyu ab05092671 Chore: update go mod 2023-02-04 13:52:19 +08:00
xjasonlyu 6809e7f835 Chore: bump gVisor 2023-01-22 13:27:11 +08:00
xjasonlyu bbdc9113d7 Chore: update go mod 2023-01-13 13:40:20 +08:00
xjasonlyu 30608f4925 Chore: bump gVisor 2023-01-01 15:55:12 +08:00
xjasonlyu 39b1406ffa Chore: update mods 2022-12-17 16:57:57 +08:00
xjasonlyu a1edb1c1bb Chore: update workflows 2022-12-17 16:53:30 +08:00
xjasonlyu ad014648ef Fix: build badges 2022-12-16 16:54:54 +08:00
xjasonlyu fa3317a94c Chore: bump go mods 2022-12-01 15:57:08 +08:00
xjasonlyu 8d3c28a516 Feature: support mark on FreeBSD & OpenBSD 2022-12-01 15:46:49 +08:00
LanceLiandGitHub 35f6888c30 Feature: support bind interface on windows (#192) 2022-11-26 23:10:23 +08:00
xjasonlyu 3cbc74b1cf Chore: update gvisor 2022-11-08 15:21:45 +08:00
xjasonlyu 24a53467f6 Chore: deprecate set-output command 2022-10-15 15:33:20 +08:00
xjasonlyu 702ba81ccd Chore: update workflows 2022-10-14 23:26:59 +08:00
xjasonlyu 7fce6e9544 Fix: PacketBufferPtr.IsNil 2022-10-14 22:54:12 +08:00
xjasonlyu 553c2f7a17 Chore: bump modules 2022-10-14 22:36:41 +08:00
xjasonlyu ccfb3a47f6 Fix: make build work
This commit may be reverted if gVisor updates its fdbased pkg.
2022-09-25 16:31:15 +08:00
xjasonlyu 0177157c69 Chore: deprecate openbsd-386 2022-09-25 16:23:47 +08:00
xjasonlyu 82546cd2c5 Chore: with unix build constraint 2022-09-25 15:49:39 +08:00
xjasonlyu 9895b3e048 Chore: update go mod 2022-09-25 15:08:23 +08:00
xjasonlyu 39b50f2bfb Chore: update go mod 2022-09-18 19:31:29 +08:00
xjasonlyu c45470650b Chore: reorder imports 2022-08-07 00:25:59 +08:00
xjasonlyu cb6408a17a Fix: update to bufferv2 2022-08-07 00:05:11 +08:00
xjasonlyu 77bd119d34 Chore: update go mod 2022-08-07 00:04:03 +08:00
xjasonlyu 595896dfc7 Chore: bump to go1.19 2022-08-06 23:51:15 +08:00
xjasonlyu 55a8d038d6 Improve: ignore tcp errors 2022-07-15 21:08:11 +08:00
xjasonlyu e31ffce0e6 Fix: adjust endpoint change 2022-07-15 20:59:37 +08:00
xjasonlyu 267cc6d1a9 Chore: update go mod 2022-07-15 20:17:27 +08:00
xjasonlyu 31468620e7 Chore: update badge logo 2022-06-01 00:10:41 +08:00
xjasonlyu 1536735456 Chore: disable blank issues 2022-05-24 15:30:51 +08:00
xjasonlyu b329f23a4e Chore: auth with GITHUB_TOKEN 2022-05-21 16:27:52 +08:00
xjasonlyu 1ecd587857 Fix(udp): ignore EOF 2022-04-26 16:06:01 +08:00
xjasonlyu 6076fd9a69 Chore(netstats): just render.JSON 2022-04-21 23:30:54 +08:00
xjasonlyu 3926f86613 Feature(docker): add tzdata 2022-04-07 10:56:24 +08:00
44 changed files with 462 additions and 249 deletions
+1 -1
View File
@@ -1,4 +1,4 @@
blank_issues_enabled: true
blank_issues_enabled: false
contact_links:
- name: tun2socks GitHub Wiki
+4 -4
View File
@@ -16,15 +16,15 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v2
uses: actions/checkout@v3
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
- name: Autobuild
uses: github/codeql-action/autobuild@v1
uses: github/codeql-action/autobuild@v2
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1
uses: github/codeql-action/analyze@v2
+12 -8
View File
@@ -20,36 +20,36 @@ jobs:
fetch-depth: 0
- name: Set up QEMU
uses: docker/setup-qemu-action@v1
uses: docker/setup-qemu-action@v2
with:
platforms: all
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
uses: docker/setup-buildx-action@v2
with:
version: latest
- name: Login to DockerHub
uses: docker/login-action@v1
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Login to GitHub Container Registry
uses: docker/login-action@v1
uses: docker/login-action@v2
with:
registry: ghcr.io
username: xjasonlyu
password: ${{ secrets.CR_PAT }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Get Version
id: shell
run: |
echo ::set-output name=version::$(git describe --tags --abbrev=0)
echo "version=$(git describe --tags --abbrev=0)" >> $GITHUB_OUTPUT
- name: Build and Push (dev)
if: github.ref == 'refs/heads/main'
uses: docker/build-push-action@v2
uses: docker/build-push-action@v3
with:
context: .
push: true
@@ -57,10 +57,12 @@ jobs:
tags: |
xjasonlyu/tun2socks:dev
ghcr.io/xjasonlyu/tun2socks:dev
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Build and Push (latest)
if: startsWith(github.ref, 'refs/tags/')
uses: docker/build-push-action@v2
uses: docker/build-push-action@v3
with:
context: .
push: true
@@ -70,3 +72,5 @@ jobs:
xjasonlyu/tun2socks:${{ steps.shell.outputs.version }}
ghcr.io/xjasonlyu/tun2socks:latest
ghcr.io/xjasonlyu/tun2socks:${{ steps.shell.outputs.version }}
cache-from: type=gha
cache-to: type=gha,mode=max
+3 -7
View File
@@ -6,15 +6,11 @@ jobs:
steps:
- uses: actions/checkout@v3
- name: Get latest go version
id: version
run: |
echo ::set-output name=go_version::$(curl -s https://raw.githubusercontent.com/actions/go-versions/main/versions-manifest.json | grep -oE '"version": "[0-9]{1}.[0-9]{1,}(.[0-9]{1,})?"' | head -1 | cut -d':' -f2 | sed 's/ //g; s/"//g')
- name: Setup Go
uses: actions/setup-go@v2
uses: actions/setup-go@v3
with:
go-version: ${{ steps.version.outputs.go_version }}
check-latest: true
go-version: '1.20'
- name: golangci-lint
uses: golangci/golangci-lint-action@v3
+4 -8
View File
@@ -15,18 +15,14 @@ jobs:
with:
fetch-depth: 0
- name: Get latest Go version
id: version
run: |
echo ::set-output name=go_version::$(curl -s https://raw.githubusercontent.com/actions/go-versions/main/versions-manifest.json | grep -oE '"version": "[0-9]{1}.[0-9]{1,}(.[0-9]{1,})?"' | head -1 | cut -d':' -f2 | sed 's/ //g; s/"//g')
- name: Setup Go
uses: actions/setup-go@v2
uses: actions/setup-go@v3
with:
go-version: ${{ steps.version.outputs.go_version }}
check-latest: true
go-version: '1.20'
- name: Cache go module
uses: actions/cache@v2
uses: actions/cache@v3
with:
path: ~/go/pkg/mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
+2 -2
View File
@@ -8,9 +8,9 @@ jobs:
stale:
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v3
- uses: actions/stale@v7
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
stale-issue-message: 'This issue is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 7 days'
exempt-issue-labels: 'question,bug,enhancement'
days-before-stale: 60
days-before-close: 7
+1 -1
View File
@@ -13,4 +13,4 @@ linters-settings:
- prefix(github.com/xjasonlyu/tun2socks)
- default
staticcheck:
go: '1.18'
go: '1.20'
+1 -1
View File
@@ -12,7 +12,7 @@ LABEL org.opencontainers.image.source="https://github.com/xjasonlyu/tun2socks"
COPY docker/entrypoint.sh /entrypoint.sh
COPY --from=builder /src/build/tun2socks /usr/bin/tun2socks
RUN apk add --update --no-cache iptables iproute2 \
RUN apk add --update --no-cache iptables iproute2 tzdata \
&& chmod +x /entrypoint.sh
ENV TUN=tun0
+5 -5
View File
@@ -41,7 +41,6 @@ UNIX_ARCH_LIST = \
linux-ppc64 \
linux-ppc64le \
linux-s390x \
openbsd-386 \
openbsd-amd64 \
openbsd-amd64-v3 \
openbsd-arm64
@@ -130,9 +129,6 @@ linux-ppc64le:
linux-s390x:
GOARCH=s390x GOOS=linux $(GO_BUILD) -o $(BUILD_DIR)/$(BINARY)-$@
openbsd-386:
GOARCH=386 GOOS=openbsd $(GO_BUILD) -o $(BUILD_DIR)/$(BINARY)-$@
openbsd-amd64:
GOARCH=amd64 GOOS=openbsd $(GO_BUILD) -o $(BUILD_DIR)/$(BINARY)-$@
@@ -171,7 +167,11 @@ all-arch: $(UNIX_ARCH_LIST) $(WINDOWS_ARCH_LIST)
releases: $(unix_releases) $(windows_releases)
lint:
golangci-lint run --disable-all -E govet -E gofumpt -E megacheck ./...
GOOS=darwin golangci-lint run ./...
GOOS=windows golangci-lint run ./...
GOOS=linux golangci-lint run ./...
GOOS=freebsd golangci-lint run ./...
GOOS=openbsd golangci-lint run ./...
clean:
rm -rf $(BUILD_DIR)
+2 -2
View File
@@ -8,13 +8,13 @@
[![Docker Pulls][6]](https://hub.docker.com/r/xjasonlyu/tun2socks)
[![Releases][7]](https://github.com/xjasonlyu/tun2socks/releases)
[1]: https://img.shields.io/github/workflow/status/xjasonlyu/tun2socks/Go?logo=github
[1]: https://img.shields.io/github/actions/workflow/status/xjasonlyu/tun2socks/release.yml?branch=main&logo=github
[2]: https://img.shields.io/github/go-mod/go-version/xjasonlyu/tun2socks?logo=go
[3]: https://goreportcard.com/badge/github.com/xjasonlyu/tun2socks
[4]: https://api.codeclimate.com/v1/badges/b5b30239174fc6603aca/maintainability
[5]: https://img.shields.io/github/license/xjasonlyu/tun2socks
[6]: https://img.shields.io/docker/pulls/xjasonlyu/tun2socks?logo=docker
[7]: https://img.shields.io/github/v/release/xjasonlyu/tun2socks
[7]: https://img.shields.io/github/v/release/xjasonlyu/tun2socks?logo=smartthings
English | [简体中文](README_ZH.md)
+2 -2
View File
@@ -8,13 +8,13 @@
[![Docker Pulls][6]](https://hub.docker.com/r/xjasonlyu/tun2socks)
[![Releases][7]](https://github.com/xjasonlyu/tun2socks/releases)
[1]: https://img.shields.io/github/workflow/status/xjasonlyu/tun2socks/Go?logo=github
[1]: https://img.shields.io/github/actions/workflow/status/xjasonlyu/tun2socks/release.yml?branch=main&logo=github
[2]: https://img.shields.io/github/go-mod/go-version/xjasonlyu/tun2socks?logo=go
[3]: https://goreportcard.com/badge/github.com/xjasonlyu/tun2socks
[4]: https://api.codeclimate.com/v1/badges/b5b30239174fc6603aca/maintainability
[5]: https://img.shields.io/github/license/xjasonlyu/tun2socks
[6]: https://img.shields.io/docker/pulls/xjasonlyu/tun2socks?logo=docker
[7]: https://img.shields.io/github/v/release/xjasonlyu/tun2socks
[7]: https://img.shields.io/github/v/release/xjasonlyu/tun2socks?logo=smartthings
[English](README.md) | 简体中文
+4 -3
View File
@@ -7,9 +7,10 @@ const (
// MaxSegmentSize is the largest possible UDP datagram size.
MaxSegmentSize = (1 << 16) - 1
// io.Copy default buffer size is 32 KiB, but the maximum packet
// size of vmess/shadowsocks is about 16 KiB, so define a buffer
// of 20 KiB to reduce the memory of each TCP relay.
// RelayBufferSize is a buffer of 20 KiB to reduce the memory
// of each TCP relay as io.Copy default buffer size is 32 KiB,
// but the maximum packet size of vmess/shadowsocks is about
// 16 KiB, so define .
RelayBufferSize = 20 << 10
)
+33
View File
@@ -0,0 +1,33 @@
package dialer
import (
"net"
"syscall"
"golang.org/x/sys/unix"
)
func setSocketOptions(network, address string, c syscall.RawConn, opts *Options) (err error) {
if opts == nil || !isTCPSocket(network) && !isUDPSocket(network) {
return
}
var innerErr error
err = c.Control(func(fd uintptr) {
host, _, _ := net.SplitHostPort(address)
if ip := net.ParseIP(host); ip != nil && !ip.IsGlobalUnicast() {
return
}
if opts.RoutingMark != 0 {
if innerErr = unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_USER_COOKIE, opts.RoutingMark); innerErr != nil {
return
}
}
})
if innerErr != nil {
err = innerErr
}
return
}
+33
View File
@@ -0,0 +1,33 @@
package dialer
import (
"net"
"syscall"
"golang.org/x/sys/unix"
)
func setSocketOptions(network, address string, c syscall.RawConn, opts *Options) (err error) {
if opts == nil || !isTCPSocket(network) && !isUDPSocket(network) {
return
}
var innerErr error
err = c.Control(func(fd uintptr) {
host, _, _ := net.SplitHostPort(address)
if ip := net.ParseIP(host); ip != nil && !ip.IsGlobalUnicast() {
return
}
if opts.RoutingMark != 0 {
if innerErr = unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_RTABLE, opts.RoutingMark); innerErr != nil {
return
}
}
})
if innerErr != nil {
err = innerErr
}
return
}
+1 -1
View File
@@ -1,4 +1,4 @@
//go:build !linux && !darwin
//go:build !unix && !windows
package dialer
+68
View File
@@ -0,0 +1,68 @@
package dialer
import (
"encoding/binary"
"net"
"syscall"
"unsafe"
"golang.org/x/sys/windows"
)
const (
IP_UNICAST_IF = 31
IPV6_UNICAST_IF = 31
)
func setSocketOptions(network, address string, c syscall.RawConn, opts *Options) (err error) {
if opts == nil || !isTCPSocket(network) && !isUDPSocket(network) {
return
}
var innerErr error
err = c.Control(func(fd uintptr) {
host, _, _ := net.SplitHostPort(address)
ip := net.ParseIP(host)
if ip != nil && !ip.IsGlobalUnicast() {
return
}
if opts.InterfaceIndex == 0 && opts.InterfaceName != "" {
if iface, err := net.InterfaceByName(opts.InterfaceName); err == nil {
opts.InterfaceIndex = iface.Index
}
}
if opts.InterfaceIndex != 0 {
switch network {
case "tcp4", "udp4":
innerErr = bindSocketToInterface4(windows.Handle(fd), uint32(opts.InterfaceIndex))
case "tcp6", "udp6":
innerErr = bindSocketToInterface6(windows.Handle(fd), uint32(opts.InterfaceIndex))
if network == "udp6" && ip == nil {
// The underlying IP net maybe IPv4 even if the `network` param is `udp6`,
// so we should bind socket to interface4 at the same time.
innerErr = bindSocketToInterface4(windows.Handle(fd), uint32(opts.InterfaceIndex))
}
}
}
})
if innerErr != nil {
err = innerErr
}
return
}
func bindSocketToInterface4(handle windows.Handle, index uint32) error {
// For IPv4, this parameter must be an interface index in network byte order.
// Ref: https://learn.microsoft.com/en-us/windows/win32/winsock/ipproto-ip-socket-options
var bytes [4]byte
binary.BigEndian.PutUint32(bytes[:], index)
index = *(*uint32)(unsafe.Pointer(&bytes[0]))
return windows.SetsockoptInt(handle, windows.IPPROTO_IP, IP_UNICAST_IF, int(index))
}
func bindSocketToInterface6(handle windows.Handle, index uint32) error {
return windows.SetsockoptInt(handle, windows.IPPROTO_IPV6, IPV6_UNICAST_IF, int(index))
}
+3 -2
View File
@@ -2,10 +2,11 @@ package obfs
import (
"bytes"
"crypto/rand"
"encoding/base64"
"fmt"
"io"
"math/rand"
mRand "math/rand"
"net"
"net/http"
@@ -65,7 +66,7 @@ func (ho *HTTPObfs) Write(b []byte) (int, error) {
randBytes := make([]byte, 16)
rand.Read(randBytes)
req, _ := http.NewRequest("GET", fmt.Sprintf("http://%s/", ho.host), bytes.NewBuffer(b[:]))
req.Header.Set("User-Agent", fmt.Sprintf("curl/7.%d.%d", rand.Int()%54, rand.Int()%2))
req.Header.Set("User-Agent", fmt.Sprintf("curl/7.%d.%d", mRand.Int()%54, mRand.Int()%2))
req.Header.Set("Upgrade", "websocket")
req.Header.Set("Connection", "Upgrade")
req.Host = ho.host
+1 -5
View File
@@ -2,19 +2,15 @@ package obfs
import (
"bytes"
"crypto/rand"
"encoding/binary"
"io"
"math/rand"
"net"
"time"
"github.com/xjasonlyu/tun2socks/v2/common/pool"
)
func init() {
rand.Seed(time.Now().Unix())
}
const (
chunkSize = 1 << 14 // 2 ** 14 == 16 * 1024
)
+2 -2
View File
@@ -6,10 +6,10 @@ import (
"fmt"
"strconv"
"github.com/xjasonlyu/tun2socks/v2/core/device"
"golang.org/x/sys/unix"
"gvisor.dev/gvisor/pkg/tcpip/stack"
"github.com/xjasonlyu/tun2socks/v2/core/device"
)
type FD struct {
+4 -2
View File
@@ -1,11 +1,13 @@
//go:build (linux && amd64) || (linux && arm64)
package fdbased
import (
"fmt"
"github.com/xjasonlyu/tun2socks/v2/core/device"
"gvisor.dev/gvisor/pkg/tcpip/link/fdbased"
"github.com/xjasonlyu/tun2socks/v2/core/device"
)
func open(fd int, mtu uint32) (device.Device, error) {
+1 -1
View File
@@ -1,4 +1,4 @@
//go:build !linux && !windows
//go:build !(linux && amd64) && !(linux && arm64) && !windows
package fdbased
+9 -11
View File
@@ -8,8 +8,8 @@ import (
"io"
"sync"
"gvisor.dev/gvisor/pkg/bufferv2"
"gvisor.dev/gvisor/pkg/tcpip"
"gvisor.dev/gvisor/pkg/tcpip/buffer"
"gvisor.dev/gvisor/pkg/tcpip/header"
"gvisor.dev/gvisor/pkg/tcpip/link/channel"
"gvisor.dev/gvisor/pkg/tcpip/stack"
@@ -110,7 +110,7 @@ func (e *Endpoint) dispatchLoop(cancel context.CancelFunc) {
}
pkt := stack.NewPacketBuffer(stack.PacketBufferOptions{
Data: buffer.View(data[offset : offset+n]).ToVectorisedView(),
Payload: bufferv2.MakeWithData(data[offset : offset+n]),
})
switch header.IPVersion(data[offset:]) {
@@ -128,7 +128,7 @@ func (e *Endpoint) dispatchLoop(cancel context.CancelFunc) {
func (e *Endpoint) outboundLoop(ctx context.Context) {
for {
pkt := e.ReadContext(ctx)
if pkt == nil {
if pkt.IsNil() {
break
}
e.writePacket(pkt)
@@ -136,19 +136,17 @@ func (e *Endpoint) outboundLoop(ctx context.Context) {
}
// writePacket writes outbound packets to the io.Writer.
func (e *Endpoint) writePacket(pkt *stack.PacketBuffer) tcpip.Error {
func (e *Endpoint) writePacket(pkt stack.PacketBufferPtr) tcpip.Error {
defer pkt.DecRef()
size := pkt.Size()
views := pkt.Views()
buf := pkt.ToBuffer()
defer buf.Release()
if e.offset != 0 {
views = append([]buffer.View{
make(buffer.View, e.offset),
}, views...)
v := bufferv2.NewViewWithData(make([]byte, e.offset))
_ = buf.Prepend(v)
}
vView := buffer.NewVectorisedView(size, views)
if _, err := e.rw.Write(vView.ToView()); err != nil {
if _, err := e.rw.Write(buf.Flatten()); err != nil {
return &tcpip.ErrInvalidEndpointState{}
}
return nil
+3 -3
View File
@@ -1,4 +1,4 @@
//go:build linux
//go:build (linux && amd64) || (linux && arm64)
package tun
@@ -6,13 +6,13 @@ import (
"fmt"
"unsafe"
"github.com/xjasonlyu/tun2socks/v2/core/device"
"golang.org/x/sys/unix"
"gvisor.dev/gvisor/pkg/tcpip/link/fdbased"
"gvisor.dev/gvisor/pkg/tcpip/link/rawfile"
"gvisor.dev/gvisor/pkg/tcpip/link/tun"
"gvisor.dev/gvisor/pkg/tcpip/stack"
"github.com/xjasonlyu/tun2socks/v2/core/device"
)
type TUN struct {
+27 -6
View File
@@ -1,14 +1,15 @@
//go:build !linux
//go:build !(linux && amd64) && !(linux && arm64)
package tun
import (
"fmt"
"sync"
"golang.zx2c4.com/wireguard/tun"
"github.com/xjasonlyu/tun2socks/v2/core/device"
"github.com/xjasonlyu/tun2socks/v2/core/device/iobased"
"golang.zx2c4.com/wireguard/tun"
)
type TUN struct {
@@ -18,6 +19,12 @@ type TUN struct {
mtu uint32
name string
offset int
rSizes []int
rBuffs [][]byte
wBuffs [][]byte
rMutex sync.Mutex
wMutex sync.Mutex
}
func Open(name string, mtu uint32) (_ device.Device, err error) {
@@ -27,7 +34,14 @@ func Open(name string, mtu uint32) (_ device.Device, err error) {
}
}()
t := &TUN{name: name, mtu: mtu, offset: offset}
t := &TUN{
name: name,
mtu: mtu,
offset: offset,
rSizes: make([]int, 1),
rBuffs: make([][]byte, 1),
wBuffs: make([][]byte, 1),
}
forcedMTU := defaultMTU
if t.mtu > 0 {
@@ -56,11 +70,18 @@ func Open(name string, mtu uint32) (_ device.Device, err error) {
}
func (t *TUN) Read(packet []byte) (int, error) {
return t.nt.Read(packet, t.offset)
t.rMutex.Lock()
defer t.rMutex.Unlock()
t.rBuffs[0] = packet
_, err := t.nt.Read(t.rBuffs, t.rSizes, t.offset)
return t.rSizes[0], err
}
func (t *TUN) Write(packet []byte) (int, error) {
return t.nt.Write(packet, t.offset)
t.wMutex.Lock()
defer t.wMutex.Unlock()
t.wBuffs[0] = packet
return t.nt.Write(t.wBuffs, t.offset)
}
func (t *TUN) Name() string {
+1 -1
View File
@@ -1,4 +1,4 @@
//go:build !linux && !windows
//go:build unix
package tun
+2 -2
View File
@@ -3,10 +3,10 @@ package core
import (
"fmt"
"github.com/xjasonlyu/tun2socks/v2/core/option"
"gvisor.dev/gvisor/pkg/tcpip"
"gvisor.dev/gvisor/pkg/tcpip/stack"
"github.com/xjasonlyu/tun2socks/v2/core/option"
)
const (
+2 -2
View File
@@ -1,11 +1,11 @@
package core
import (
"github.com/xjasonlyu/tun2socks/v2/core/option"
"gvisor.dev/gvisor/pkg/tcpip"
"gvisor.dev/gvisor/pkg/tcpip/header"
"gvisor.dev/gvisor/pkg/tcpip/stack"
"github.com/xjasonlyu/tun2socks/v2/core/option"
)
func withRouteTable(nicID tcpip.NICID) option.Option {
+5 -13
View File
@@ -1,9 +1,6 @@
package core
import (
"github.com/xjasonlyu/tun2socks/v2/core/adapter"
"github.com/xjasonlyu/tun2socks/v2/core/option"
"gvisor.dev/gvisor/pkg/tcpip"
"gvisor.dev/gvisor/pkg/tcpip/network/ipv4"
"gvisor.dev/gvisor/pkg/tcpip/network/ipv6"
@@ -11,6 +8,9 @@ import (
"gvisor.dev/gvisor/pkg/tcpip/transport/icmp"
"gvisor.dev/gvisor/pkg/tcpip/transport/tcp"
"gvisor.dev/gvisor/pkg/tcpip/transport/udp"
"github.com/xjasonlyu/tun2socks/v2/core/adapter"
"github.com/xjasonlyu/tun2socks/v2/core/option"
)
// Config is the configuration to create *stack.Stack.
@@ -23,10 +23,6 @@ type Config struct {
// stack to set transport handlers.
TransportHandler adapter.TransportHandler
// PrintFunc is the function that will be called
// to print internal stack events.
PrintFunc func(string, ...any)
// Options are supplement options to apply settings
// for the internal stack.
Options []option.Option
@@ -34,10 +30,6 @@ type Config struct {
// CreateStack creates *stack.Stack with given config.
func CreateStack(cfg *Config) (*stack.Stack, error) {
if cfg.PrintFunc == nil {
cfg.PrintFunc = func(string, ...any) {}
}
opts := []option.Option{option.WithDefault()}
if len(opts) > 0 {
opts = append(opts, cfg.Options...)
@@ -64,8 +56,8 @@ func CreateStack(cfg *Config) (*stack.Stack, error) {
// before creating NIC, otherwise NIC would dispatch packets
// to stack and cause race condition.
// Initiate transport protocol (TCP/UDP) with given handler.
withTCPHandler(cfg.TransportHandler.HandleTCP, cfg.PrintFunc),
withUDPHandler(cfg.TransportHandler.HandleUDP, cfg.PrintFunc),
withTCPHandler(cfg.TransportHandler.HandleTCP),
withUDPHandler(cfg.TransportHandler.HandleUDP),
// Create stack NIC and then bind link endpoint to it.
withCreatingNIC(nicID, cfg.LinkEndpoint),
+6 -5
View File
@@ -3,15 +3,16 @@ package core
import (
"time"
"github.com/xjasonlyu/tun2socks/v2/core/adapter"
"github.com/xjasonlyu/tun2socks/v2/core/option"
glog "gvisor.dev/gvisor/pkg/log"
"gvisor.dev/gvisor/pkg/tcpip"
"gvisor.dev/gvisor/pkg/tcpip/adapters/gonet"
"gvisor.dev/gvisor/pkg/tcpip/header"
"gvisor.dev/gvisor/pkg/tcpip/stack"
"gvisor.dev/gvisor/pkg/tcpip/transport/tcp"
"gvisor.dev/gvisor/pkg/waiter"
"github.com/xjasonlyu/tun2socks/v2/core/adapter"
"github.com/xjasonlyu/tun2socks/v2/core/option"
)
const (
@@ -40,7 +41,7 @@ const (
tcpKeepaliveInterval = 30 * time.Second
)
func withTCPHandler(handle func(adapter.TCPConn), printf func(string, ...any)) option.Option {
func withTCPHandler(handle func(adapter.TCPConn)) option.Option {
return func(s *stack.Stack) error {
tcpForwarder := tcp.NewForwarder(s, defaultWndSize, maxConnAttempts, func(r *tcp.ForwarderRequest) {
var (
@@ -52,7 +53,7 @@ func withTCPHandler(handle func(adapter.TCPConn), printf func(string, ...any)) o
defer func() {
if err != nil {
printf("forward tcp request %s:%d->%s:%d: %s",
glog.Debugf("forward tcp request: %s:%d->%s:%d: %s",
id.RemoteAddress, id.RemotePort, id.LocalAddress, id.LocalPort, err)
}
}()
+6 -5
View File
@@ -1,16 +1,17 @@
package core
import (
"github.com/xjasonlyu/tun2socks/v2/core/adapter"
"github.com/xjasonlyu/tun2socks/v2/core/option"
glog "gvisor.dev/gvisor/pkg/log"
"gvisor.dev/gvisor/pkg/tcpip/adapters/gonet"
"gvisor.dev/gvisor/pkg/tcpip/stack"
"gvisor.dev/gvisor/pkg/tcpip/transport/udp"
"gvisor.dev/gvisor/pkg/waiter"
"github.com/xjasonlyu/tun2socks/v2/core/adapter"
"github.com/xjasonlyu/tun2socks/v2/core/option"
)
func withUDPHandler(handle func(adapter.UDPConn), printf func(string, ...any)) option.Option {
func withUDPHandler(handle func(adapter.UDPConn)) option.Option {
return func(s *stack.Stack) error {
udpForwarder := udp.NewForwarder(s, func(r *udp.ForwarderRequest) {
var (
@@ -19,7 +20,7 @@ func withUDPHandler(handle func(adapter.UDPConn), printf func(string, ...any)) o
)
ep, err := r.CreateEndpoint(&wq)
if err != nil {
printf("udp forwarder request %s:%d->%s:%d: %s",
glog.Debugf("forward udp request: %s:%d->%s:%d: %s",
id.RemoteAddress, id.RemotePort, id.LocalAddress, id.LocalPort, err)
return
}
+31 -9
View File
@@ -2,11 +2,16 @@ package engine
import (
"errors"
"fmt"
"net"
"os/exec"
"strings"
"sync"
"time"
"github.com/docker/go-units"
"gvisor.dev/gvisor/pkg/tcpip"
"gvisor.dev/gvisor/pkg/tcpip/stack"
"github.com/xjasonlyu/tun2socks/v2/component/dialer"
"github.com/xjasonlyu/tun2socks/v2/core"
"github.com/xjasonlyu/tun2socks/v2/core/device"
@@ -16,10 +21,6 @@ import (
"github.com/xjasonlyu/tun2socks/v2/proxy"
"github.com/xjasonlyu/tun2socks/v2/restapi"
"github.com/xjasonlyu/tun2socks/v2/tunnel"
"github.com/docker/go-units"
"gvisor.dev/gvisor/pkg/tcpip"
"gvisor.dev/gvisor/pkg/tcpip/stack"
)
var (
@@ -91,6 +92,15 @@ func stop() (err error) {
return err
}
func execCommand(cmd string) error {
parts := strings.Fields(cmd)
if len(parts) == 0 {
return errors.New("empty command")
}
_, err := exec.Command(parts[0], parts[1:]...).Output()
return err
}
func general(k *Key) error {
level, err := log.ParseLevel(k.LogLevel)
if err != nil {
@@ -159,6 +169,21 @@ func netstack(k *Key) (err error) {
return errors.New("empty device")
}
if k.TUNPreUp != "" {
if preUpErr := execCommand(k.TUNPreUp); preUpErr != nil {
log.Warnf("[TUN] failed to pre-execute: %s: %v", k.TUNPreUp, preUpErr)
}
}
defer func() {
if k.TUNPostUp == "" || err != nil {
return
}
if postUpErr := execCommand(k.TUNPostUp); postUpErr != nil {
log.Warnf("[TUN] failed to post-execute: %s: %v", k.TUNPostUp, postUpErr)
}
}()
if _defaultProxy, err = parseProxy(k.Proxy); err != nil {
return
}
@@ -192,10 +217,7 @@ func netstack(k *Key) (err error) {
if _defaultStack, err = core.CreateStack(&core.Config{
LinkEndpoint: _defaultDevice,
TransportHandler: &mirror.Tunnel{},
PrintFunc: func(format string, v ...any) {
log.Warnf("[STACK] %s", fmt.Sprintf(format, v...))
},
Options: opts,
Options: opts,
}); err != nil {
return
}
+2
View File
@@ -13,5 +13,7 @@ type Key struct {
TCPModerateReceiveBuffer bool `yaml:"tcp-moderate-receive-buffer"`
TCPSendBufferSize string `yaml:"tcp-send-buffer-size"`
TCPReceiveBufferSize string `yaml:"tcp-receive-buffer-size"`
TUNPreUp string `yaml:"tun-pre-up"`
TUNPostUp string `yaml:"tun-post-up"`
UDPTimeout time.Duration `yaml:"udp-timeout"`
}
+19 -18
View File
@@ -1,32 +1,33 @@
module github.com/xjasonlyu/tun2socks/v2
go 1.18
go 1.20
require (
github.com/Dreamacro/go-shadowsocks2 v0.1.7
github.com/docker/go-units v0.4.0
github.com/go-chi/chi/v5 v5.0.7
github.com/go-chi/cors v1.2.0
github.com/go-chi/render v1.0.1
github.com/Dreamacro/go-shadowsocks2 v0.1.8
github.com/docker/go-units v0.5.0
github.com/go-chi/chi/v5 v5.0.8
github.com/go-chi/cors v1.2.1
github.com/go-chi/render v1.0.2
github.com/google/uuid v1.3.0
github.com/gorilla/websocket v1.5.0
github.com/sirupsen/logrus v1.8.1
github.com/sirupsen/logrus v1.9.0
github.com/stretchr/testify v1.7.1
go.uber.org/atomic v1.9.0
go.uber.org/automaxprocs v1.5.1
golang.org/x/sys v0.0.0-20220405210540-1e041c57c461
golang.org/x/time v0.0.0-20220224211638-0e9765cccd65
golang.zx2c4.com/wireguard v0.0.0-20220318042302-193cf8d6a5d6
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
gvisor.dev/gvisor v0.0.0-20220405222207-795f4f0139bb
go.uber.org/atomic v1.10.0
go.uber.org/automaxprocs v1.5.2
golang.org/x/sys v0.7.0
golang.org/x/time v0.3.0
golang.zx2c4.com/wireguard v0.0.0-20230325221338-052af4a8072b
gopkg.in/yaml.v3 v3.0.1
gvisor.dev/gvisor v0.0.0-20230401011607-0333bf067633
)
require (
github.com/ajg/form v1.5.1 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/google/btree v1.0.1 // indirect
github.com/google/btree v1.1.2 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
golang.org/x/crypto v0.0.0-20220331220935-ae2d96664a29 // indirect
golang.org/x/net v0.0.0-20220403103023-749bd193bc2b // indirect
golang.zx2c4.com/wintun v0.0.0-20211104114900-415007cec224 // indirect
golang.org/x/crypto v0.7.0 // indirect
golang.org/x/net v0.8.0 // indirect
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
)
+38 -43
View File
@@ -1,19 +1,21 @@
github.com/Dreamacro/go-shadowsocks2 v0.1.7 h1:8CtbE1HoPPMfrQZGXmlluq6dO2lL31W6WRRE8fabc4Q=
github.com/Dreamacro/go-shadowsocks2 v0.1.7/go.mod h1:8p5G4cAj5ZlXwUR+Ww63gfSikr8kvw8uw3TDwLAJpUc=
github.com/Dreamacro/go-shadowsocks2 v0.1.8 h1:Ixejp5JscEc866gAvm/l6TFd7BOBvDviKgwb1quWw3g=
github.com/Dreamacro/go-shadowsocks2 v0.1.8/go.mod h1:51y4Q6tJoCE7e8TmYXcQRqfoxPfE9Cvn79V6pB6Df7Y=
github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU=
github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
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/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw=
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/go-chi/chi/v5 v5.0.7 h1:rDTPXLDHGATaeHvVlLcR4Qe0zftYethFucbjVQ1PxU8=
github.com/go-chi/chi/v5 v5.0.7/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
github.com/go-chi/cors v1.2.0 h1:tV1g1XENQ8ku4Bq3K9ub2AtgG+p16SmzeMSGTwrOKdE=
github.com/go-chi/cors v1.2.0/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58=
github.com/go-chi/render v1.0.1 h1:4/5tis2cKaNdnv9zFLfXzcquC9HbeZgCnxGnKrltBS8=
github.com/go-chi/render v1.0.1/go.mod h1:pq4Rr7HbnsdaeHagklXub+p6Wd16Af5l9koip1OvJns=
github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4=
github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA=
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/go-chi/chi/v5 v5.0.8 h1:lD+NLqFcAi1ovnVZpsnObHGW4xb4J8lNmoYVfECH1Y0=
github.com/go-chi/chi/v5 v5.0.8/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
github.com/go-chi/cors v1.2.1 h1:xEC8UT3Rlp2QuWNEr4Fs/c2EAGVKBwy/1vHx3bppil4=
github.com/go-chi/cors v1.2.1/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58=
github.com/go-chi/render v1.0.2 h1:4ER/udB0+fMWB2Jlf15RV3F4A2FDuYi/9f+lFttR/Lg=
github.com/go-chi/render v1.0.2/go.mod h1:/gr3hVkmYR0YlEy3LxCuVRFzEu9Ruok+gFqbIofjao0=
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/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
@@ -24,40 +26,33 @@ github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
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/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g=
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/automaxprocs v1.5.1 h1:e1YG66Lrk73dn4qhg8WFSvhF0JuFQF0ERIp4rpuV8Qk=
go.uber.org/automaxprocs v1.5.1/go.mod h1:BF4eumQw0P9GtnuxxovUd06vwm1o18oMzFtK66vU6XU=
golang.org/x/crypto v0.0.0-20210317152858-513c2a44f670/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20220331220935-ae2d96664a29 h1:tkVvjkPTB7pnW3jnid7kNyAMPVWllTNOf/qKDze4p9o=
golang.org/x/crypto v0.0.0-20220331220935-ae2d96664a29/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220403103023-749bd193bc2b h1:vI32FkLJNAWtGD4BwkThwEy6XS7ZLLMHkSkYfF8M0W0=
golang.org/x/net v0.0.0-20220403103023-749bd193bc2b/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20220405210540-1e041c57c461 h1:kHVeDEnfKn3T238CvrUcz6KeEsFHVaKh4kMTt6Wsysg=
golang.org/x/sys v0.0.0-20220405210540-1e041c57c461/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/time v0.0.0-20220224211638-0e9765cccd65 h1:M73Iuj3xbbb9Uk1DYhzydthsj6oOd6l9bpuFcNoUvTs=
golang.org/x/time v0.0.0-20220224211638-0e9765cccd65/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.zx2c4.com/wintun v0.0.0-20211104114900-415007cec224 h1:Ug9qvr1myri/zFN6xL17LSCBGFDnphBBhzmILHsM5TY=
golang.zx2c4.com/wintun v0.0.0-20211104114900-415007cec224/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI=
golang.zx2c4.com/wireguard v0.0.0-20220318042302-193cf8d6a5d6 h1:kgBK1EGuTIYbwoKROmsoV0FQp08gnCcVa110A4Unqhk=
golang.zx2c4.com/wireguard v0.0.0-20220318042302-193cf8d6a5d6/go.mod h1:bVQfyl2sCM/QIIGHpWbFGfHPuDvqnCNkT6MQLTCjO/U=
go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ=
go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
go.uber.org/automaxprocs v1.5.2 h1:2LxUOGiR3O6tw8ui5sZa2LAaHnsviZdVOUZw4fvbnME=
go.uber.org/automaxprocs v1.5.2/go.mod h1:eRbA25aqJrxAbsLO0xy5jVwPt7FQnRgjW+efnwa1WM0=
golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A=
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ=
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
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-20230325221338-052af4a8072b h1:J1CaxgLerRR5lgx3wnr6L04cJFbWoceSK9JWBdglINo=
golang.zx2c4.com/wireguard v0.0.0-20230325221338-052af4a8072b/go.mod h1:tqur9LnfstdR9ep2LaJT4lFUl0EjlHtge+gAjmsHUG4=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gvisor.dev/gvisor v0.0.0-20220405222207-795f4f0139bb h1:AFXQ8bzBy3bvv18rPD8bjDGzylB0PZrMJWQKuXxvR7Y=
gvisor.dev/gvisor v0.0.0-20220405222207-795f4f0139bb/go.mod h1:tWwEcFvJavs154OdjFCw78axNrsDlz4Zh8jvPqwcpGI=
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-20230401011607-0333bf067633 h1:trSjCkJT04PkOY8WayMOlk9MV6SK2LqvMBRnoi9jy5E=
gvisor.dev/gvisor v0.0.0-20230401011607-0333bf067633/go.mod h1:pzr6sy8gDLfVmDAg8OYrlKvGEHw5C3PGTiBXBTCx76Q=
+34
View File
@@ -0,0 +1,34 @@
package log
import (
"io"
"runtime"
"strings"
"time"
glog "gvisor.dev/gvisor/pkg/log"
)
func init() {
EnableStackLog(true)
}
func EnableStackLog(v bool) {
if v {
glog.SetTarget(&emitter{}) // built-in logger
} else {
glog.SetTarget(&glog.Writer{Next: io.Discard})
}
}
type emitter struct{}
func (emitter) Emit(depth int, level glog.Level, _ time.Time, format string, args ...any) {
if _, file, line, ok := runtime.Caller(depth + 1); ok {
// Ignore (*gonet.TCPConn).RemoteAddr() warning: `ep.GetRemoteAddress() failed`.
if line == 457 && strings.HasSuffix(file, "/pkg/tcpip/adapters/gonet/gonet.go") {
return
}
}
logf(Level(level)+2, "[STACK] "+format, args...)
}
+5 -3
View File
@@ -7,13 +7,13 @@ import (
"os/signal"
"syscall"
"go.uber.org/automaxprocs/maxprocs"
"gopkg.in/yaml.v3"
_ "github.com/xjasonlyu/tun2socks/v2/dns"
"github.com/xjasonlyu/tun2socks/v2/engine"
"github.com/xjasonlyu/tun2socks/v2/internal/version"
"github.com/xjasonlyu/tun2socks/v2/log"
"go.uber.org/automaxprocs/maxprocs"
"gopkg.in/yaml.v3"
)
var (
@@ -36,6 +36,8 @@ func init() {
flag.StringVar(&key.TCPSendBufferSize, "tcp-sndbuf", "", "Set TCP send buffer size for netstack")
flag.StringVar(&key.TCPReceiveBufferSize, "tcp-rcvbuf", "", "Set TCP receive buffer size for netstack")
flag.BoolVar(&key.TCPModerateReceiveBuffer, "tcp-auto-tuning", false, "Enable TCP receive buffer auto-tuning")
flag.StringVar(&key.TUNPreUp, "tun-pre-up", "", "Execute a command before TUN device setup")
flag.StringVar(&key.TUNPostUp, "tun-post-up", "", "Execute a command after TUN device setup")
flag.BoolVar(&versionFlag, "version", false, "Show version and then quit")
flag.Parse()
}
+2 -2
View File
@@ -6,13 +6,13 @@ import (
"fmt"
"net"
"github.com/Dreamacro/go-shadowsocks2/core"
"github.com/xjasonlyu/tun2socks/v2/component/dialer"
obfs "github.com/xjasonlyu/tun2socks/v2/component/simple-obfs"
M "github.com/xjasonlyu/tun2socks/v2/metadata"
"github.com/xjasonlyu/tun2socks/v2/proxy/proto"
"github.com/xjasonlyu/tun2socks/v2/transport/socks5"
"github.com/Dreamacro/go-shadowsocks2/core"
)
var _ Proxy = (*Shadowsocks)(nil)
+4
View File
@@ -121,6 +121,10 @@ func (ss *Socks5) DialUDP(*M.Metadata) (_ net.PacketConn, err error) {
}()
bindAddr := addr.UDPAddr()
if bindAddr == nil {
return nil, fmt.Errorf("invalid UDP binding address: %#v", addr)
}
if bindAddr.IP.IsUnspecified() { /* e.g. "0.0.0.0" or "::" */
udpAddr, err := net.ResolveUDPAddr("udp", ss.Addr())
if err != nil {
+2 -2
View File
@@ -7,11 +7,11 @@ import (
"strconv"
"time"
"github.com/xjasonlyu/tun2socks/v2/tunnel/statistic"
"github.com/go-chi/chi/v5"
"github.com/go-chi/render"
"github.com/gorilla/websocket"
"github.com/xjasonlyu/tun2socks/v2/tunnel/statistic"
)
const defaultInterval = 1000
-1
View File
@@ -40,7 +40,6 @@ func getNetStats(w http.ResponseWriter, r *http.Request) {
if !websocket.IsWebSocketUpgrade(r) {
w.Header().Set("Content-Type", "application/json")
render.Status(r, http.StatusOK)
// write and flush.
w.Write(snapshot())
w.(http.Flusher).Flush()
return
+4 -4
View File
@@ -10,14 +10,14 @@ import (
"strings"
"time"
V "github.com/xjasonlyu/tun2socks/v2/internal/version"
"github.com/xjasonlyu/tun2socks/v2/log"
"github.com/xjasonlyu/tun2socks/v2/tunnel/statistic"
"github.com/go-chi/chi/v5"
"github.com/go-chi/cors"
"github.com/go-chi/render"
"github.com/gorilla/websocket"
V "github.com/xjasonlyu/tun2socks/v2/internal/version"
"github.com/xjasonlyu/tun2socks/v2/log"
"github.com/xjasonlyu/tun2socks/v2/tunnel/statistic"
)
var (
+29 -4
View File
@@ -1,13 +1,14 @@
package statistic
import (
"errors"
"net"
"time"
M "github.com/xjasonlyu/tun2socks/v2/metadata"
"github.com/google/uuid"
"go.uber.org/atomic"
M "github.com/xjasonlyu/tun2socks/v2/metadata"
)
type tracker interface {
@@ -30,7 +31,7 @@ type tcpTracker struct {
manager *Manager
}
func NewTCPTracker(conn net.Conn, metadata *M.Metadata, manager *Manager) *tcpTracker {
func NewTCPTracker(conn net.Conn, metadata *M.Metadata, manager *Manager) net.Conn {
id, _ := uuid.NewRandom()
tt := &tcpTracker{
@@ -49,6 +50,11 @@ func NewTCPTracker(conn net.Conn, metadata *M.Metadata, manager *Manager) *tcpTr
return tt
}
// DefaultTCPTracker returns a new net.Conn(*tcpTacker) with default manager.
func DefaultTCPTracker(conn net.Conn, metadata *M.Metadata) net.Conn {
return NewTCPTracker(conn, metadata, DefaultManager)
}
func (tt *tcpTracker) ID() string {
return tt.UUID.String()
}
@@ -74,6 +80,20 @@ func (tt *tcpTracker) Close() error {
return tt.Conn.Close()
}
func (tt *tcpTracker) CloseRead() error {
if cr, ok := tt.Conn.(interface{ CloseRead() error }); ok {
return cr.CloseRead()
}
return errors.New("CloseRead is not implemented")
}
func (tt *tcpTracker) CloseWrite() error {
if cw, ok := tt.Conn.(interface{ CloseWrite() error }); ok {
return cw.CloseWrite()
}
return errors.New("CloseWrite is not implemented")
}
type udpTracker struct {
net.PacketConn `json:"-"`
@@ -81,7 +101,7 @@ type udpTracker struct {
manager *Manager
}
func NewUDPTracker(conn net.PacketConn, metadata *M.Metadata, manager *Manager) *udpTracker {
func NewUDPTracker(conn net.PacketConn, metadata *M.Metadata, manager *Manager) net.PacketConn {
id, _ := uuid.NewRandom()
ut := &udpTracker{
@@ -100,6 +120,11 @@ func NewUDPTracker(conn net.PacketConn, metadata *M.Metadata, manager *Manager)
return ut
}
// DefaultUDPTracker returns a new net.PacketConn(*udpTacker) with default manager.
func DefaultUDPTracker(conn net.PacketConn, metadata *M.Metadata) net.PacketConn {
return NewUDPTracker(conn, metadata, DefaultManager)
}
func (ut *udpTracker) ID() string {
return ut.UUID.String()
}
+28 -37
View File
@@ -15,17 +15,14 @@ import (
)
const (
tcpWaitTimeout = 5 * time.Second
// tcpWaitTimeout implements a TCP half-close timeout.
tcpWaitTimeout = 60 * time.Second
)
func newTCPTracker(conn net.Conn, metadata *M.Metadata) net.Conn {
return statistic.NewTCPTracker(conn, metadata, statistic.DefaultManager)
}
func handleTCPConn(originConn adapter.TCPConn) {
defer originConn.Close()
func handleTCPConn(localConn adapter.TCPConn) {
defer localConn.Close()
id := localConn.ID()
id := originConn.ID()
metadata := &M.Metadata{
Network: M.TCP,
SrcIP: net.IP(id.RemoteAddress),
@@ -34,51 +31,45 @@ func handleTCPConn(localConn adapter.TCPConn) {
DstPort: id.LocalPort,
}
targetConn, err := proxy.Dial(metadata)
remoteConn, err := proxy.Dial(metadata)
if err != nil {
log.Warnf("[TCP] dial %s: %v", metadata.DestinationAddress(), err)
return
}
metadata.MidIP, metadata.MidPort = parseAddr(targetConn.LocalAddr())
metadata.MidIP, metadata.MidPort = parseAddr(remoteConn.LocalAddr())
targetConn = newTCPTracker(targetConn, metadata)
defer targetConn.Close()
remoteConn = statistic.DefaultTCPTracker(remoteConn, metadata)
defer remoteConn.Close()
log.Infof("[TCP] %s <-> %s", metadata.SourceAddress(), metadata.DestinationAddress())
relay(localConn, targetConn) /* relay connections */
pipe(originConn, remoteConn)
}
// relay copies between left and right bidirectionally.
func relay(left, right net.Conn) {
// pipe copies copy data to & from provided net.Conn(s) bidirectionally.
func pipe(origin, remote net.Conn) {
wg := sync.WaitGroup{}
wg.Add(2)
go func() {
defer wg.Done()
if err := copyBuffer(right, left); err != nil {
log.Warnf("[TCP] %v", err)
}
right.SetReadDeadline(time.Now().Add(tcpWaitTimeout))
}()
go func() {
defer wg.Done()
if err := copyBuffer(left, right); err != nil {
log.Warnf("[TCP] %v", err)
}
left.SetReadDeadline(time.Now().Add(tcpWaitTimeout))
}()
go unidirectionalStream(remote, origin, "origin->remote", &wg)
go unidirectionalStream(origin, remote, "remote->origin", &wg)
wg.Wait()
}
func copyBuffer(dst io.Writer, src io.Reader) error {
func unidirectionalStream(dst, src net.Conn, dir string, wg *sync.WaitGroup) {
defer wg.Done()
buf := pool.Get(pool.RelayBufferSize)
defer pool.Put(buf)
_, err := io.CopyBuffer(dst, src, buf)
if ne, ok := err.(net.Error); ok && ne.Timeout() {
return nil /* ignore I/O timeout */
if _, err := io.CopyBuffer(dst, src, buf); err != nil {
log.Debugf("[TCP] copy data for %s: %v", dir, err)
}
return err
pool.Put(buf)
// Do the upload/download side TCP half-close.
if cr, ok := src.(interface{ CloseRead() error }); ok {
cr.CloseRead()
}
if cw, ok := dst.(interface{ CloseWrite() error }); ok {
cw.CloseWrite()
}
// Set TCP half-close timeout.
dst.SetReadDeadline(time.Now().Add(tcpWaitTimeout))
}
+16 -21
View File
@@ -1,6 +1,7 @@
package tunnel
import (
"io"
"net"
"sync"
"time"
@@ -20,10 +21,6 @@ func SetUDPTimeout(t time.Duration) {
_udpSessionTimeout = t
}
func newUDPTracker(conn net.PacketConn, metadata *M.Metadata) net.PacketConn {
return statistic.NewUDPTracker(conn, metadata, statistic.DefaultManager)
}
// TODO: Port Restricted NAT support.
func handleUDPConn(uc adapter.UDPConn) {
defer uc.Close()
@@ -44,7 +41,7 @@ func handleUDPConn(uc adapter.UDPConn) {
}
metadata.MidIP, metadata.MidPort = parseAddr(pc.LocalAddr())
pc = newUDPTracker(pc, metadata)
pc = statistic.DefaultUDPTracker(pc, metadata)
defer pc.Close()
var remote net.Addr
@@ -56,31 +53,27 @@ func handleUDPConn(uc adapter.UDPConn) {
pc = newSymmetricNATPacketConn(pc, metadata)
log.Infof("[UDP] %s <-> %s", metadata.SourceAddress(), metadata.DestinationAddress())
relayPacket(uc, pc, remote)
pipePacket(uc, pc, remote)
}
func relayPacket(left net.PacketConn, right net.PacketConn, to net.Addr) {
func pipePacket(origin, remote net.PacketConn, to net.Addr) {
wg := sync.WaitGroup{}
wg.Add(2)
go func() {
defer wg.Done()
if err := copyPacketBuffer(right, left, to, _udpSessionTimeout); err != nil {
log.Warnf("[UDP] %v", err)
}
}()
go func() {
defer wg.Done()
if err := copyPacketBuffer(left, right, nil, _udpSessionTimeout); err != nil {
log.Warnf("[UDP] %v", err)
}
}()
go unidirectionalPacketStream(remote, origin, to, "origin->remote", &wg)
go unidirectionalPacketStream(origin, remote, nil, "remote->origin", &wg)
wg.Wait()
}
func copyPacketBuffer(dst net.PacketConn, src net.PacketConn, to net.Addr, timeout time.Duration) error {
func unidirectionalPacketStream(dst, src net.PacketConn, to net.Addr, dir string, wg *sync.WaitGroup) {
defer wg.Done()
if err := copyPacketData(dst, src, to, _udpSessionTimeout); err != nil {
log.Debugf("[UDP] copy data for %s: %v", dir, err)
}
}
func copyPacketData(dst, src net.PacketConn, to net.Addr, timeout time.Duration) error {
buf := pool.Get(pool.MaxSegmentSize)
defer pool.Put(buf)
@@ -89,6 +82,8 @@ func copyPacketBuffer(dst net.PacketConn, src net.PacketConn, to net.Addr, timeo
n, _, err := src.ReadFrom(buf)
if ne, ok := err.(net.Error); ok && ne.Timeout() {
return nil /* ignore I/O timeout */
} else if err == io.EOF {
return nil /* ignore EOF */
} else if err != nil {
return err
}