tun: add route config

This commit is contained in:
ginuerzh 2019-12-27 14:08:17 +08:00
parent a01dbfc88c
commit 4a9731a512
7 changed files with 135 additions and 56 deletions

View File

@ -6,6 +6,7 @@ import (
"fmt"
"net"
"os"
"strings"
"time"
"github.com/ginuerzh/gost"
@ -413,9 +414,10 @@ func (r *route) GenRouters() ([]router, error) {
handler = gost.SNIHandler()
case "tun":
cfg := gost.TunConfig{
Name: node.Get("name"),
Addr: node.Get("net"),
MTU: node.GetInt("mtu"),
Name: node.Get("name"),
Addr: node.Get("net"),
MTU: node.GetInt("mtu"),
Routes: strings.Split(node.Get("route"), ","),
}
handler = gost.TunHandler(node.Remote, gost.TunConfigHandlerOption(cfg))
default:

2
go.mod
View File

@ -10,7 +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/docker/libcontainer v2.2.1+incompatible
github.com/ginuerzh/gosocks4 v0.0.1
github.com/ginuerzh/gosocks5 v0.2.0
github.com/ginuerzh/tls-dissector v0.0.1

26
tun.go
View File

@ -12,6 +12,7 @@ import (
"github.com/shadowsocks/go-shadowsocks2/core"
"github.com/songgao/water"
"golang.org/x/net/ipv4"
"golang.org/x/net/ipv6"
)
type TunConfig struct {
@ -117,6 +118,12 @@ func (h *tunHandler) transportTun(tun net.Conn, conn net.PacketConn, raddr net.A
}
if header.Version != ipv4.Version {
if Debug && header.Version == ipv6.Version {
if hdr, _ := ipv6.ParseHeader(b[:n]); hdr != nil {
log.Logf("[tun] %s: %s -> %s %d %d",
tun.LocalAddr(), hdr.Src, hdr.Dst, hdr.PayloadLen, hdr.TrafficClass)
}
}
log.Logf("[tun] %s: v%d ignored, only support ipv4",
tun.LocalAddr(), header.Version)
return nil
@ -127,13 +134,14 @@ func (h *tunHandler) transportTun(tun net.Conn, conn net.PacketConn, raddr net.A
addr = v.(net.Addr)
}
if addr == nil {
log.Logf("[tun] %s: no address to forward for %s -> %s",
tun.LocalAddr(), header.Src, header.Dst)
log.Logf("[tun] %s: no route for %s -> %s %d/%d %x %d %d",
tun.LocalAddr(), header.Src, header.Dst,
header.Len, header.TotalLen, header.ID, header.Flags, header.Protocol)
return nil
}
if Debug {
log.Logf("[tun] %s >>> %s: %s -> %s %d/%d %x %x %d",
log.Logf("[tun] %s >>> %s: %s -> %s %d/%d %x %d %d",
tun.LocalAddr(), addr, header.Src, header.Dst,
header.Len, header.TotalLen, header.ID, header.Flags, header.Protocol)
}
@ -169,23 +177,31 @@ func (h *tunHandler) transportTun(tun net.Conn, conn net.PacketConn, raddr net.A
}
if header.Version != ipv4.Version {
if Debug && header.Version == ipv6.Version {
if hdr, _ := ipv6.ParseHeader(b[:n]); hdr != nil {
log.Logf("[tun] %s <<< %s: %s -> %s %d %d",
tun.LocalAddr(), addr, hdr.Src, hdr.Dst, hdr.PayloadLen, hdr.TrafficClass)
}
}
log.Logf("[tun] %s <- %s: v%d ignored, only support ipv4",
tun.LocalAddr(), addr, header.Version)
return nil
}
if Debug {
log.Logf("[tun] %s <<< %s: %s -> %s %d/%d %x %x %d",
log.Logf("[tun] %s <<< %s: %s -> %s %d/%d %x %d %d",
tun.LocalAddr(), addr, header.Src, header.Dst,
header.Len, header.TotalLen, header.ID, header.Flags, header.Protocol)
}
if h.ipNet != nil && h.ipNet.Contains(header.Src) {
if h.ipNet != nil && h.ipNet.IP.Equal(header.Src.Mask(h.ipNet.Mask)) {
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, addr, actual.(net.Addr))
}
} else {
log.Logf("[tun] %s: record route: %s -> %s", tun.LocalAddr(), header.Src, addr)
}
}

View File

@ -1,44 +0,0 @@
// +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
}

View File

@ -3,8 +3,11 @@
package gost
import (
"fmt"
"net"
"github.com/docker/libcontainer/netlink"
"github.com/go-log/log"
"github.com/milosgajdos83/tenus"
"github.com/songgao/water"
)
@ -34,13 +37,29 @@ func createTun(cfg TunConfig) (conn net.Conn, ipNet *net.IPNet, err error) {
if mtu <= 0 {
mtu = DefaultMTU
}
if err = link.SetLinkMTU(mtu); err != nil {
cmd := fmt.Sprintf("ip link set dev %s mtu %d", ifce.Name(), mtu)
log.Log("[tun]", cmd)
if er := link.SetLinkMTU(mtu); er != nil {
err = fmt.Errorf("%s: %v", cmd, er)
return
}
if err = link.SetLinkIp(ip, ipNet); err != nil {
cmd = fmt.Sprintf("ip address add %s dev %s", cfg.Addr, ifce.Name())
log.Log("[tun]", cmd)
if er := link.SetLinkIp(ip, ipNet); er != nil {
err = fmt.Errorf("%s: %v", cmd, er)
return
}
if err = link.SetLinkUp(); err != nil {
cmd = fmt.Sprintf("ip link set dev %s up", ifce.Name())
log.Log("[tun]", cmd)
if er := link.SetLinkUp(); er != nil {
err = fmt.Errorf("%s: %v", cmd, er)
return
}
if err = addRoutes(ifce.Name(), cfg.Routes...); err != nil {
return
}
@ -50,3 +69,17 @@ func createTun(cfg TunConfig) (conn net.Conn, ipNet *net.IPNet, err error) {
}
return
}
func addRoutes(ifName string, routes ...string) error {
for _, route := range routes {
if route == "" {
continue
}
cmd := fmt.Sprintf("ip route add %s dev %s", route, ifName)
log.Log("[tun]", cmd)
if err := netlink.AddRoute(route, "", "", ifName); err != nil {
return fmt.Errorf("%s: %v", cmd, err)
}
}
return nil
}

70
tun_unix.go Normal file
View File

@ -0,0 +1,70 @@
// +build !linux,!windows
package gost
import (
"fmt"
"net"
"os/exec"
"strconv"
"github.com/go-log/log"
"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
}
cmd := fmt.Sprintf("ifconfig %s inet %s mtu %d up", ifce.Name(), cfg.Addr, mtu)
log.Log("[tun]", cmd)
if er := exec.Command(
"ifconfig", ifce.Name(),
"inet", cfg.Addr,
"mtu", strconv.Itoa(mtu),
"up").Run(); er != nil {
err = fmt.Errorf("%s: %v", cmd, er)
return
}
if err = addRoutes(ifce.Name(), cfg.Routes...); err != nil {
return
}
conn = &tunConn{
ifce: ifce,
addr: &net.IPAddr{IP: ip},
}
return
}
func addRoutes(ifName string, routes ...string) error {
for _, route := range routes {
if route == "" {
continue
}
cmd := fmt.Sprintf("route add -net %s -interface %s", route, ifName)
log.Log("[tun]", cmd)
if er := exec.Command(
"route", "add",
"-net", route,
"-interface", ifName).Run(); er != nil {
return fmt.Errorf("%s: %v", cmd, er)
}
}
return nil
}

View File

@ -7,6 +7,8 @@ import (
"net"
)
//TODO: wintun for Windows: https://www.wintun.net/
// https://godoc.org/golang.zx2c4.com/wireguard/tun/wintun
func createTun(cfg TunConfig) (conn net.Conn, ipNet *net.IPNet, err error) {
err = errors.New("tun is not supported on Windows")
return