tun: add route config
This commit is contained in:
parent
a01dbfc88c
commit
4a9731a512
@ -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
2
go.mod
@ -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
26
tun.go
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
39
tun_linux.go
39
tun_linux.go
@ -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
70
tun_unix.go
Normal 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
|
||||
}
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user