tun: add route config
This commit is contained in:
parent
a01dbfc88c
commit
4a9731a512
@ -6,6 +6,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ginuerzh/gost"
|
"github.com/ginuerzh/gost"
|
||||||
@ -413,9 +414,10 @@ func (r *route) GenRouters() ([]router, error) {
|
|||||||
handler = gost.SNIHandler()
|
handler = gost.SNIHandler()
|
||||||
case "tun":
|
case "tun":
|
||||||
cfg := gost.TunConfig{
|
cfg := gost.TunConfig{
|
||||||
Name: node.Get("name"),
|
Name: node.Get("name"),
|
||||||
Addr: node.Get("net"),
|
Addr: node.Get("net"),
|
||||||
MTU: node.GetInt("mtu"),
|
MTU: node.GetInt("mtu"),
|
||||||
|
Routes: strings.Split(node.Get("route"), ","),
|
||||||
}
|
}
|
||||||
handler = gost.TunHandler(node.Remote, gost.TunConfigHandlerOption(cfg))
|
handler = gost.TunHandler(node.Remote, gost.TunConfigHandlerOption(cfg))
|
||||||
default:
|
default:
|
||||||
|
2
go.mod
2
go.mod
@ -10,7 +10,7 @@ require (
|
|||||||
github.com/bifurcation/mint v0.0.0-20181105071958-a14404e9a861 // indirect
|
github.com/bifurcation/mint v0.0.0-20181105071958-a14404e9a861 // indirect
|
||||||
github.com/cheekybits/genny v1.0.0 // indirect
|
github.com/cheekybits/genny v1.0.0 // indirect
|
||||||
github.com/dchest/siphash v1.2.1 // 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/gosocks4 v0.0.1
|
||||||
github.com/ginuerzh/gosocks5 v0.2.0
|
github.com/ginuerzh/gosocks5 v0.2.0
|
||||||
github.com/ginuerzh/tls-dissector v0.0.1
|
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/shadowsocks/go-shadowsocks2/core"
|
||||||
"github.com/songgao/water"
|
"github.com/songgao/water"
|
||||||
"golang.org/x/net/ipv4"
|
"golang.org/x/net/ipv4"
|
||||||
|
"golang.org/x/net/ipv6"
|
||||||
)
|
)
|
||||||
|
|
||||||
type TunConfig struct {
|
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 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",
|
log.Logf("[tun] %s: v%d ignored, only support ipv4",
|
||||||
tun.LocalAddr(), header.Version)
|
tun.LocalAddr(), header.Version)
|
||||||
return nil
|
return nil
|
||||||
@ -127,13 +134,14 @@ func (h *tunHandler) transportTun(tun net.Conn, conn net.PacketConn, raddr net.A
|
|||||||
addr = v.(net.Addr)
|
addr = v.(net.Addr)
|
||||||
}
|
}
|
||||||
if addr == nil {
|
if addr == nil {
|
||||||
log.Logf("[tun] %s: no address to forward for %s -> %s",
|
log.Logf("[tun] %s: no route for %s -> %s %d/%d %x %d %d",
|
||||||
tun.LocalAddr(), header.Src, header.Dst)
|
tun.LocalAddr(), header.Src, header.Dst,
|
||||||
|
header.Len, header.TotalLen, header.ID, header.Flags, header.Protocol)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if Debug {
|
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,
|
tun.LocalAddr(), addr, header.Src, header.Dst,
|
||||||
header.Len, header.TotalLen, header.ID, header.Flags, header.Protocol)
|
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 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",
|
log.Logf("[tun] %s <- %s: v%d ignored, only support ipv4",
|
||||||
tun.LocalAddr(), addr, header.Version)
|
tun.LocalAddr(), addr, header.Version)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if Debug {
|
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,
|
tun.LocalAddr(), addr, header.Src, header.Dst,
|
||||||
header.Len, header.TotalLen, header.ID, header.Flags, header.Protocol)
|
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, loaded := routes.LoadOrStore(header.Src.String(), addr); loaded {
|
||||||
if actual.(net.Addr).String() != addr.String() {
|
if actual.(net.Addr).String() != addr.String() {
|
||||||
log.Logf("[tun] %s <- %s: unexpected address mapping %s -> %s(actual %s)",
|
log.Logf("[tun] %s <- %s: unexpected address mapping %s -> %s(actual %s)",
|
||||||
tun.LocalAddr(), addr, header.Dst, addr, actual.(net.Addr))
|
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
|
package gost
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
|
"github.com/docker/libcontainer/netlink"
|
||||||
|
"github.com/go-log/log"
|
||||||
"github.com/milosgajdos83/tenus"
|
"github.com/milosgajdos83/tenus"
|
||||||
"github.com/songgao/water"
|
"github.com/songgao/water"
|
||||||
)
|
)
|
||||||
@ -34,13 +37,29 @@ func createTun(cfg TunConfig) (conn net.Conn, ipNet *net.IPNet, err error) {
|
|||||||
if mtu <= 0 {
|
if mtu <= 0 {
|
||||||
mtu = DefaultMTU
|
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
|
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
|
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
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,3 +69,17 @@ func createTun(cfg TunConfig) (conn net.Conn, ipNet *net.IPNet, err error) {
|
|||||||
}
|
}
|
||||||
return
|
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"
|
"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) {
|
func createTun(cfg TunConfig) (conn net.Conn, ipNet *net.IPNet, err error) {
|
||||||
err = errors.New("tun is not supported on Windows")
|
err = errors.New("tun is not supported on Windows")
|
||||||
return
|
return
|
||||||
|
Loading…
Reference in New Issue
Block a user