tun: replace ip command with syscall

This commit is contained in:
ginuerzh 2019-12-27 09:47:06 +08:00
parent b11ce8a71c
commit 81ac55a019
6 changed files with 124 additions and 50 deletions

2
go.mod
View File

@ -10,6 +10,7 @@ require (
github.com/bifurcation/mint v0.0.0-20181105071958-a14404e9a861 // indirect
github.com/cheekybits/genny v1.0.0 // indirect
github.com/dchest/siphash v1.2.1 // indirect
github.com/docker/libcontainer v2.2.1+incompatible // indirect
github.com/ginuerzh/gosocks4 v0.0.1
github.com/ginuerzh/gosocks5 v0.2.0
github.com/ginuerzh/tls-dissector v0.0.1
@ -25,6 +26,7 @@ require (
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.3
github.com/milosgajdos83/tenus v0.0.0-20190415114537-1f3ed00ae7d8
github.com/onsi/ginkgo v1.7.0 // indirect
github.com/onsi/gomega v1.4.3 // indirect
github.com/pkg/errors v0.8.1 // indirect

4
go.sum
View File

@ -16,6 +16,8 @@ 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=
github.com/dchest/siphash v1.2.1/go.mod h1:q+IRvb2gOSrUnYoPqHiyHXS0FOBBOdl6tONBlVnOnt4=
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/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/ginuerzh/gosocks4 v0.0.1 h1:ojDKUyz+uaEeRm2usY1cyQiXTqJqrKxfeE6SVBXq4m0=
@ -52,6 +54,8 @@ github.com/lucas-clemente/quic-go-certificates v0.0.0-20160823095156-d2f86524cce
github.com/lucas-clemente/quic-go-certificates v0.0.0-20160823095156-d2f86524cced/go.mod h1:NCcRLrOTZbzhZvixZLlERbJtDtYsmMw8Jc4vS8Z0g58=
github.com/miekg/dns v1.1.3 h1:1g0r1IvskvgL8rR+AcHzUA+oFmGcQlaIm4IqakufeMM=
github.com/miekg/dns v1.1.3/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/milosgajdos83/tenus v0.0.0-20190415114537-1f3ed00ae7d8 h1:4WFQEfEJ7zaHYViIVM2Cd6tnQOOhiEHbmQtlcV7aOpc=
github.com/milosgajdos83/tenus v0.0.0-20190415114537-1f3ed00ae7d8/go.mod h1:G95Wwn625/q6JCCytI4VR/a5VtPwrtI0B+Q1Gi38QLA=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs=
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=

51
tun.go
View File

@ -5,8 +5,6 @@ import (
"io"
"net"
"os"
"os/exec"
"strconv"
"sync"
"time"
@ -26,6 +24,7 @@ type TunConfig struct {
type tunHandler struct {
raddr string
options *HandlerOptions
ipNet *net.IPNet
}
// TunHandler creates a handler for tun tunnel.
@ -92,52 +91,10 @@ func (h *tunHandler) Handle(conn net.Conn) {
}
func (h *tunHandler) createTun() (conn net.Conn, err error) {
cfg := h.options.TunConfig
ip, _, err := net.ParseCIDR(cfg.Addr)
if err != nil {
conn, h.ipNet, err = createTun(h.options.TunConfig)
return
}
ifce, err := water.New(water.Config{
DeviceType: water.TUN,
PlatformSpecificParams: water.PlatformSpecificParams{
Name: cfg.Name,
},
})
if err != nil {
return
}
setup := func(args ...string) error {
cmd := exec.Command("/sbin/ip", args...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
return cmd.Run()
}
mtu := cfg.MTU
if mtu <= 0 {
mtu = DefaultMTU
}
if err = setup("link", "set", "dev", ifce.Name(), "mtu", strconv.Itoa(mtu)); err != nil {
return
}
if err = setup("addr", "add", cfg.Addr, "dev", ifce.Name()); err != nil {
return
}
if err = setup("link", "set", "dev", ifce.Name(), "up"); err != nil {
return
}
tc := &tunConn{
ifce: ifce,
addr: &net.IPAddr{IP: ip},
}
return tc, nil
}
func (h *tunHandler) transportTun(tun net.Conn, conn net.PacketConn, raddr net.Addr) error {
var routes sync.Map
errc := make(chan error, 1)
@ -223,10 +180,12 @@ func (h *tunHandler) transportTun(tun net.Conn, conn net.PacketConn, raddr net.A
header.Len, header.TotalLen, header.ID, header.Flags, header.Protocol)
}
if h.ipNet != nil && h.ipNet.Contains(header.Src) {
if actual, loaded := routes.LoadOrStore(header.Src.String(), addr); loaded {
if actual.(net.Addr).String() != addr.String() {
log.Logf("[tun] %s <- %s: unexpected address mapping %s -> %s(actual %s)",
tun.LocalAddr(), addr, header.Dst.String(), addr, actual.(net.Addr).String())
tun.LocalAddr(), addr, header.Dst, addr, actual.(net.Addr))
}
}
}

44
tun_darwin.go Normal file
View File

@ -0,0 +1,44 @@
// +build darwin
package gost
import (
"net"
"os/exec"
"strconv"
"github.com/songgao/water"
)
func createTun(cfg TunConfig) (conn net.Conn, ipNet *net.IPNet, err error) {
ip, ipNet, err := net.ParseCIDR(cfg.Addr)
if err != nil {
return
}
ifce, err := water.New(water.Config{
DeviceType: water.TUN,
})
if err != nil {
return
}
mtu := cfg.MTU
if mtu <= 0 {
mtu = DefaultMTU
}
if err = exec.Command(
"ifconfig", ifce.Name(),
"inet", cfg.Addr,
"mtu", strconv.Itoa(mtu),
"up").Run(); err != nil {
return
}
conn = &tunConn{
ifce: ifce,
addr: &net.IPAddr{IP: ip},
}
return
}

52
tun_linux.go Normal file
View File

@ -0,0 +1,52 @@
// +build linux
package gost
import (
"net"
"github.com/milosgajdos83/tenus"
"github.com/songgao/water"
)
func createTun(cfg TunConfig) (conn net.Conn, ipNet *net.IPNet, err error) {
ip, ipNet, err := net.ParseCIDR(cfg.Addr)
if err != nil {
return
}
ifce, err := water.New(water.Config{
DeviceType: water.TUN,
PlatformSpecificParams: water.PlatformSpecificParams{
Name: cfg.Name,
},
})
if err != nil {
return
}
link, err := tenus.NewLinkFrom(ifce.Name())
if err != nil {
return
}
mtu := cfg.MTU
if mtu <= 0 {
mtu = DefaultMTU
}
if err = link.SetLinkMTU(mtu); err != nil {
return
}
if err = link.SetLinkIp(ip, ipNet); err != nil {
return
}
if err = link.SetLinkUp(); err != nil {
return
}
conn = &tunConn{
ifce: ifce,
addr: &net.IPAddr{IP: ip},
}
return
}

13
tun_win.go Normal file
View File

@ -0,0 +1,13 @@
// +build windows
package gost
import (
"errors"
"net"
)
func createTun(cfg TunConfig) (conn net.Conn, ipNet *net.IPNet, err error) {
err = errors.New("tun is not supported on Windows")
return
}