From c0c477493d77b1c14c19722512aad0656b41746d Mon Sep 17 00:00:00 2001 From: ginuerzh Date: Mon, 6 Jan 2020 13:05:20 +0800 Subject: [PATCH] tuntap: add raw tcp tunnel --- README.md | 5 ++-- README_en.md | 5 ++-- cmd/gost/route.go | 12 +++++++-- go.mod | 8 +++--- go.sum | 13 ++++++++++ tuntap.go | 63 ++++++++++++++++++++++++++++++++++++++++++++--- 6 files changed, 93 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 952df50..9b09492 100644 --- a/README.md +++ b/README.md @@ -31,13 +31,14 @@ gost - GO Simple Tunnel * [负载均衡](https://docs.ginuerzh.xyz/gost/load-balancing/) * [路由控制](https://docs.ginuerzh.xyz/gost/bypass/) * [DNS控制](https://docs.ginuerzh.xyz/gost/dns/) +* [TUN/TAP设备](https://docs.ginuerzh.xyz/gost/tuntap/) Wiki站点: -Google讨论组: - Telegram讨论群: +Google讨论组: + 安装 ------ diff --git a/README_en.md b/README_en.md index ce3a257..13ad50c 100644 --- a/README_en.md +++ b/README_en.md @@ -28,13 +28,14 @@ Features * [Load balancing](https://docs.ginuerzh.xyz/gost/en/load-balancing/) * [Routing control](https://docs.ginuerzh.xyz/gost/en/bypass/) * [DNS control](https://docs.ginuerzh.xyz/gost/en/dns/) +* [TUN/TAP device](https://docs.ginuerzh.xyz/gost/en/tuntap/) Wiki: -Google group: - Telegram group: +Google group: + Installation ------ diff --git a/cmd/gost/route.go b/cmd/gost/route.go index 8eef1f1..4ea5548 100644 --- a/cmd/gost/route.go +++ b/cmd/gost/route.go @@ -395,9 +395,17 @@ func (r *route) GenRouters() ([]router, error) { case "ohttp": ln, err = gost.ObfsHTTPListener(node.Addr) case "tun": - ln, err = gost.TunListener(node.Addr) + ln, err = gost.TunListener(node.Addr, + gost.TunListenConfig{ + TCP: node.GetBool("tcp"), + RemoteAddr: node.Remote, + }) case "tap": - ln, err = gost.TapListener(node.Addr) + ln, err = gost.TapListener(node.Addr, + gost.TapListenConfig{ + TCP: node.GetBool("tcp"), + RemoteAddr: node.Remote, + }) default: ln, err = gost.TCPListener(node.Addr) } diff --git a/go.mod b/go.mod index 96a3898..27a189d 100644 --- a/go.mod +++ b/go.mod @@ -9,6 +9,7 @@ require ( github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da // indirect github.com/bifurcation/mint v0.0.0-20181105071958-a14404e9a861 // indirect github.com/cheekybits/genny v1.0.0 // indirect + github.com/coreos/go-iptables v0.4.5 // indirect github.com/dchest/siphash v1.2.1 // indirect github.com/docker/libcontainer v2.2.1+incompatible github.com/ginuerzh/gosocks4 v0.0.1 @@ -17,6 +18,7 @@ require ( github.com/go-log/log v0.1.0 github.com/gobwas/glob v0.2.3 github.com/golang/mock v1.2.0 // indirect + github.com/google/gopacket v1.1.17 // indirect github.com/gorilla/websocket v1.4.0 // indirect github.com/hashicorp/golang-lru v0.5.0 // indirect github.com/klauspost/compress v1.4.1 @@ -37,10 +39,10 @@ require ( github.com/templexxx/cpufeat v0.0.0-20180724012125-cef66df7f161 // indirect github.com/templexxx/xor v0.0.0-20181023030647-4e92f724b73b // indirect github.com/tjfoc/gmsm v1.0.1 // indirect - golang.org/x/crypto v0.0.0-20190130090550-b01c7a725664 - golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3 + github.com/xtaci/tcpraw v1.2.25 + golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 + golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 // indirect - golang.org/x/sys v0.0.0-20190228124157-a34e9553db1e // indirect gopkg.in/gorilla/websocket.v1 v1.4.0 gopkg.in/xtaci/kcp-go.v4 v4.3.2 gopkg.in/xtaci/smux.v1 v1.0.7 diff --git a/go.sum b/go.sum index 41f44a7..a548b91 100644 --- a/go.sum +++ b/go.sum @@ -12,6 +12,8 @@ github.com/bifurcation/mint v0.0.0-20181105071958-a14404e9a861 h1:x17NvoJaphEzay github.com/bifurcation/mint v0.0.0-20181105071958-a14404e9a861/go.mod h1:zVt7zX3K/aDCk9Tj+VM7YymsX66ERvzCJzw8rFCX2JU= github.com/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitfE= github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ= +github.com/coreos/go-iptables v0.4.5 h1:DpHb9vJrZQEFMcVLFKAAGMUVX0XoRC0ptCthinRYm38= +github.com/coreos/go-iptables v0.4.5/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/dchest/siphash v1.2.1 h1:4cLinnzVJDKxTCl9B01807Yiy+W7ZzVHj/KIroQRvT4= @@ -34,6 +36,8 @@ github.com/golang/mock v1.2.0 h1:28o5sBqPkBsMGnC6b4MvE2TzSr5/AT4c/1fLqVGIwlk= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/google/gopacket v1.1.17 h1:rMrlX2ZY2UbvT+sdz3+6J+pp2z+msCq9MxTU6ymxbBY= +github.com/google/gopacket v1.1.17/go.mod h1:UdDNZ1OO62aGYVnPhxT1U6aI7ukYtA/kB8vaU0diBUM= github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/hashicorp/golang-lru v0.5.0 h1:CL2msUPvZTLb5O648aiLNJw3hnBxN2+1Jq8rCOH9wdo= @@ -77,19 +81,28 @@ github.com/templexxx/xor v0.0.0-20181023030647-4e92f724b73b h1:mnG1fcsIB1d/3vbkB github.com/templexxx/xor v0.0.0-20181023030647-4e92f724b73b/go.mod h1:5XA7W9S6mni3h5uvOC75dA3m9CCCaS83lltmc0ukdi4= github.com/tjfoc/gmsm v1.0.1 h1:R11HlqhXkDospckjZEihx9SW/2VW0RgdwrykyWMFOQU= github.com/tjfoc/gmsm v1.0.1/go.mod h1:XxO4hdhhrzAd+G4CjDqaOkd0hUzmtPR/d3EiBBMn/wc= +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/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190130090550-b01c7a725664 h1:YbZJ76lQ1BqNhVe7dKTSB67wDrc2VPRR75IyGyyPDX8= golang.org/x/crypto v0.0.0-20190130090550-b01c7a725664/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3 h1:ulvT7fqt0yHWzpJwI57MezWnYDVpCAYBVuYst/L+fAY= golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 h1:YUO/7uOKsKeq9UokNS62b8FYywz3ker1l1vDZRCRefw= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/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-20190228124157-a34e9553db1e h1:ZytStCyV048ZqDsWHiYDdoI2Vd4msMcrDECFxS+tL9c= golang.org/x/sys v0.0.0-20190228124157-a34e9553db1e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190405154228-4b34438f7a67 h1:1Fzlr8kkDLQwqMP8GxrhptBLqZG/EDpiATneiZHY998= +golang.org/x/sys v0.0.0-20190405154228-4b34438f7a67/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= diff --git a/tuntap.go b/tuntap.go index db137c0..927a246 100644 --- a/tuntap.go +++ b/tuntap.go @@ -14,6 +14,7 @@ import ( "github.com/shadowsocks/go-shadowsocks2/core" "github.com/songgao/water" "github.com/songgao/water/waterutil" + "github.com/xtaci/tcpraw" "golang.org/x/net/ipv4" "golang.org/x/net/ipv6" ) @@ -290,14 +291,20 @@ func (h *tunHandler) transportTun(tun net.Conn, conn net.PacketConn, raddr net.A return err } +type TunListenConfig struct { + TCP bool + RemoteAddr string +} + type tunListener struct { addr net.Addr conns chan net.Conn closed chan struct{} + config TunListenConfig } // TunListener creates a listener for tun tunnel. -func TunListener(addr string) (Listener, error) { +func TunListener(addr string, cfg TunListenConfig) (Listener, error) { laddr, err := net.ResolveUDPAddr("udp", addr) if err != nil { return nil, err @@ -308,10 +315,22 @@ func TunListener(addr string) (Listener, error) { addr: laddr, conns: make(chan net.Conn, threads), closed: make(chan struct{}), + config: cfg, } for i := 0; i < threads; i++ { - conn, err := net.ListenUDP("udp", laddr) + var conn net.Conn + if cfg.TCP { + var c *tcpraw.TCPConn + if cfg.RemoteAddr != "" { + c, err = tcpraw.Dial("tcp", cfg.RemoteAddr) + } else { + c, err = tcpraw.Listen("tcp", addr) + } + conn = &rawTCPConn{c} + } else { + conn, err = net.ListenUDP("udp", laddr) + } if err != nil { return nil, err } @@ -592,14 +611,20 @@ func (h *tapHandler) transportTap(tap net.Conn, conn net.PacketConn, raddr net.A return err } +type TapListenConfig struct { + TCP bool + RemoteAddr string +} + type tapListener struct { addr net.Addr conns chan net.Conn closed chan struct{} + config TapListenConfig } // TapListener creates a listener for tap tunnel. -func TapListener(addr string) (Listener, error) { +func TapListener(addr string, cfg TapListenConfig) (Listener, error) { laddr, err := net.ResolveUDPAddr("udp", addr) if err != nil { return nil, err @@ -610,10 +635,22 @@ func TapListener(addr string) (Listener, error) { addr: laddr, conns: make(chan net.Conn, threads), closed: make(chan struct{}), + config: cfg, } for i := 0; i < threads; i++ { - conn, err := net.ListenUDP("udp", laddr) + var conn net.Conn + if cfg.TCP { + var c *tcpraw.TCPConn + if cfg.RemoteAddr != "" { + c, err = tcpraw.Dial("tcp", cfg.RemoteAddr) + } else { + c, err = tcpraw.Listen("tcp", addr) + } + conn = &rawTCPConn{c} + } else { + conn, err = net.ListenUDP("udp", laddr) + } if err != nil { return nil, err } @@ -684,6 +721,24 @@ func (c *tunTapConn) SetWriteDeadline(t time.Time) error { return &net.OpError{Op: "set", Net: "tuntap", Source: nil, Addr: nil, Err: errors.New("deadline not supported")} } +type rawTCPConn struct { + *tcpraw.TCPConn +} + +func (c *rawTCPConn) Read(b []byte) (n int, err error) { + err = &net.OpError{Op: "read", Net: "rawtcp", Source: nil, Addr: nil, Err: errors.New("read not supported")} + return +} + +func (c *rawTCPConn) Write(b []byte) (n int, err error) { + err = &net.OpError{Op: "write", Net: "rawtcp", Source: nil, Addr: nil, Err: errors.New("write not supported")} + return +} + +func (c *rawTCPConn) RemoteAddr() net.Addr { + return &net.IPAddr{} +} + func IsIPv6Multicast(addr net.HardwareAddr) bool { return addr[0] == 0x33 && addr[1] == 0x33 }