add gateway per route for tun server side
This commit is contained in:
parent
c3aedc6d42
commit
e16427c6c8
@ -7,6 +7,7 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"net"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
@ -273,3 +274,44 @@ func parseHosts(s string) *gost.Hosts {
|
|||||||
|
|
||||||
return hosts
|
return hosts
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func parseIPRoutes(s string) (routes []gost.IPRoute) {
|
||||||
|
if s == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
file, err := os.Open(s)
|
||||||
|
if err != nil {
|
||||||
|
ss := strings.Split(s, ",")
|
||||||
|
for _, s := range ss {
|
||||||
|
if _, inet, _ := net.ParseCIDR(strings.TrimSpace(s)); inet != nil {
|
||||||
|
routes = append(routes, gost.IPRoute{Dest: inet})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
defer file.Close()
|
||||||
|
scanner := bufio.NewScanner(file)
|
||||||
|
for scanner.Scan() {
|
||||||
|
line := strings.Replace(scanner.Text(), "\t", " ", -1)
|
||||||
|
line = strings.TrimSpace(line)
|
||||||
|
if line == "" || strings.HasPrefix(line, "#") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
var route gost.IPRoute
|
||||||
|
ss := strings.Split(line, " ")
|
||||||
|
if len(ss) > 0 && ss[0] != "" {
|
||||||
|
_, route.Dest, _ = net.ParseCIDR(strings.TrimSpace(ss[0]))
|
||||||
|
if route.Dest == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(ss) > 1 && ss[1] != "" {
|
||||||
|
route.Gateway = net.ParseIP(ss[1])
|
||||||
|
}
|
||||||
|
routes = append(routes, route)
|
||||||
|
}
|
||||||
|
return routes
|
||||||
|
}
|
||||||
|
@ -311,6 +311,8 @@ func (r *route) GenRouters() ([]router, error) {
|
|||||||
ttl = time.Duration(node.GetInt("ttl")) * time.Second
|
ttl = time.Duration(node.GetInt("ttl")) * time.Second
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tunRoutes := parseIPRoutes(node.Get("route"))
|
||||||
|
|
||||||
var ln gost.Listener
|
var ln gost.Listener
|
||||||
switch node.Transport {
|
switch node.Transport {
|
||||||
case "tls":
|
case "tls":
|
||||||
@ -415,7 +417,7 @@ func (r *route) GenRouters() ([]router, error) {
|
|||||||
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"), ","),
|
Routes: tunRoutes,
|
||||||
Gateway: node.Get("gw"),
|
Gateway: node.Get("gw"),
|
||||||
}
|
}
|
||||||
ln, err = gost.TunListener(cfg)
|
ln, err = gost.TunListener(cfg)
|
||||||
@ -525,6 +527,7 @@ func (r *route) GenRouters() ([]router, error) {
|
|||||||
gost.NodeHandlerOption(node),
|
gost.NodeHandlerOption(node),
|
||||||
gost.IPsHandlerOption(ips),
|
gost.IPsHandlerOption(ips),
|
||||||
gost.TCPModeHandlerOption(node.GetBool("tcp")),
|
gost.TCPModeHandlerOption(node.GetBool("tcp")),
|
||||||
|
gost.IPRoutesHandlerOption(tunRoutes...),
|
||||||
)
|
)
|
||||||
|
|
||||||
rt := router{
|
rt := router{
|
||||||
|
@ -41,6 +41,7 @@ type HandlerOptions struct {
|
|||||||
Host string
|
Host string
|
||||||
IPs []string
|
IPs []string
|
||||||
TCPMode bool
|
TCPMode bool
|
||||||
|
IPRoutes []IPRoute
|
||||||
}
|
}
|
||||||
|
|
||||||
// HandlerOption allows a common way to set handler options.
|
// HandlerOption allows a common way to set handler options.
|
||||||
@ -203,6 +204,13 @@ func TCPModeHandlerOption(b bool) HandlerOption {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IPRoutesHandlerOption sets the IP routes for tun tunnel.
|
||||||
|
func IPRoutesHandlerOption(routes ...IPRoute) HandlerOption {
|
||||||
|
return func(opts *HandlerOptions) {
|
||||||
|
opts.IPRoutes = routes
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type autoHandler struct {
|
type autoHandler struct {
|
||||||
options *HandlerOptions
|
options *HandlerOptions
|
||||||
}
|
}
|
||||||
|
32
tuntap.go
32
tuntap.go
@ -39,11 +39,16 @@ func ipProtocol(p waterutil.IPProtocol) string {
|
|||||||
return fmt.Sprintf("unknown(%d)", p)
|
return fmt.Sprintf("unknown(%d)", p)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type IPRoute struct {
|
||||||
|
Dest *net.IPNet
|
||||||
|
Gateway net.IP
|
||||||
|
}
|
||||||
|
|
||||||
type TunConfig struct {
|
type TunConfig struct {
|
||||||
Name string
|
Name string
|
||||||
Addr string
|
Addr string
|
||||||
MTU int
|
MTU int
|
||||||
Routes []string
|
Routes []IPRoute
|
||||||
Gateway string
|
Gateway string
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -224,6 +229,20 @@ func (h *tunHandler) initTunnelConn(pc net.PacketConn) (net.PacketConn, error) {
|
|||||||
return pc, nil
|
return pc, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (h *tunHandler) findRouteFor(dst net.IP) net.Addr {
|
||||||
|
for _, route := range h.options.IPRoutes {
|
||||||
|
if route.Dest.Contains(dst) && route.Gateway != nil {
|
||||||
|
if v, ok := h.routes.Load(ipToTunRouteKey(route.Gateway)); ok {
|
||||||
|
return v.(net.Addr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if v, ok := h.routes.Load(ipToTunRouteKey(dst)); ok {
|
||||||
|
return v.(net.Addr)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (h *tunHandler) transportTun(tun net.Conn, conn net.PacketConn, raddr net.Addr) error {
|
func (h *tunHandler) transportTun(tun net.Conn, conn net.PacketConn, raddr net.Addr) error {
|
||||||
errc := make(chan error, 1)
|
errc := make(chan error, 1)
|
||||||
|
|
||||||
@ -279,10 +298,7 @@ func (h *tunHandler) transportTun(tun net.Conn, conn net.PacketConn, raddr net.A
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var addr net.Addr
|
addr := h.findRouteFor(dst)
|
||||||
if v, ok := h.routes.Load(ipToTunRouteKey(dst)); ok {
|
|
||||||
addr = v.(net.Addr)
|
|
||||||
}
|
|
||||||
if addr == nil {
|
if addr == nil {
|
||||||
log.Logf("[tun] no route for %s -> %s", src, dst)
|
log.Logf("[tun] no route for %s -> %s", src, dst)
|
||||||
return nil
|
return nil
|
||||||
@ -361,11 +377,11 @@ func (h *tunHandler) transportTun(tun net.Conn, conn net.PacketConn, raddr net.A
|
|||||||
log.Logf("[tun] new route: %s -> %s", src, addr)
|
log.Logf("[tun] new route: %s -> %s", src, addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
if v, ok := h.routes.Load(ipToTunRouteKey(dst)); ok {
|
if addr := h.findRouteFor(dst); addr != nil {
|
||||||
if Debug {
|
if Debug {
|
||||||
log.Logf("[tun] find route: %s -> %s", dst, v)
|
log.Logf("[tun] find route: %s -> %s", dst, addr)
|
||||||
}
|
}
|
||||||
_, err := conn.WriteTo(b[:n], v.(net.Addr))
|
_, err := conn.WriteTo(b[:n], addr)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ func createTun(cfg TunConfig) (conn net.Conn, itf *net.Interface, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = addRoutes(ifce.Name(), cfg.Routes...); err != nil {
|
if err = addTunRoutes(ifce.Name(), cfg.Routes...); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -58,12 +58,12 @@ func createTap(cfg TapConfig) (conn net.Conn, itf *net.Interface, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func addRoutes(ifName string, routes ...string) error {
|
func addTunRoutes(ifName string, routes ...IPRoute) error {
|
||||||
for _, route := range routes {
|
for _, route := range routes {
|
||||||
if route == "" {
|
if route.Dest == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
cmd := fmt.Sprintf("route add -net %s -interface %s", route, ifName)
|
cmd := fmt.Sprintf("route add -net %s -interface %s", route.Dest.String(), ifName)
|
||||||
log.Log("[tun]", cmd)
|
log.Log("[tun]", cmd)
|
||||||
args := strings.Split(cmd, " ")
|
args := strings.Split(cmd, " ")
|
||||||
if er := exec.Command(args[0], args[1:]...).Run(); er != nil {
|
if er := exec.Command(args[0], args[1:]...).Run(); er != nil {
|
||||||
|
@ -136,14 +136,14 @@ func createTap(cfg TapConfig) (conn net.Conn, itf *net.Interface, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func addTunRoutes(ifName string, routes ...string) error {
|
func addTunRoutes(ifName string, routes ...IPRoute) error {
|
||||||
for _, route := range routes {
|
for _, route := range routes {
|
||||||
if route == "" {
|
if route.Dest == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
cmd := fmt.Sprintf("ip route add %s dev %s", route, ifName)
|
cmd := fmt.Sprintf("ip route add %s dev %s", route.Dest.String(), ifName)
|
||||||
log.Logf("[tun] %s", cmd)
|
log.Logf("[tun] %s", cmd)
|
||||||
if err := netlink.AddRoute(route, "", "", ifName); err != nil {
|
if err := netlink.AddRoute(route.Dest.String(), "", "", ifName); err != nil {
|
||||||
return fmt.Errorf("%s: %v", cmd, err)
|
return fmt.Errorf("%s: %v", cmd, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -96,12 +96,12 @@ func createTap(cfg TapConfig) (conn net.Conn, itf *net.Interface, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func addTunRoutes(ifName string, routes ...string) error {
|
func addTunRoutes(ifName string, routes ...IPRoute) error {
|
||||||
for _, route := range routes {
|
for _, route := range routes {
|
||||||
if route == "" {
|
if route.Dest == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
cmd := fmt.Sprintf("route add -net %s -interface %s", route, ifName)
|
cmd := fmt.Sprintf("route add -net %s -interface %s", route.Dest.String(), ifName)
|
||||||
log.Logf("[tun] %s", cmd)
|
log.Logf("[tun] %s", cmd)
|
||||||
args := strings.Split(cmd, " ")
|
args := strings.Split(cmd, " ")
|
||||||
if er := exec.Command(args[0], args[1:]...).Run(); er != nil {
|
if er := exec.Command(args[0], args[1:]...).Run(); er != nil {
|
||||||
|
@ -98,16 +98,16 @@ func createTap(cfg TapConfig) (conn net.Conn, itf *net.Interface, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func addTunRoutes(ifName string, gw string, routes ...string) error {
|
func addTunRoutes(ifName string, gw string, routes ...IPRoute) error {
|
||||||
for _, route := range routes {
|
for _, route := range routes {
|
||||||
if route == "" {
|
if route.Dest == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
deleteRoute(ifName, route)
|
deleteRoute(ifName, route.Dest.String())
|
||||||
|
|
||||||
cmd := fmt.Sprintf("netsh interface ip add route prefix=%s interface=%s store=active",
|
cmd := fmt.Sprintf("netsh interface ip add route prefix=%s interface=%s store=active",
|
||||||
route, ifName)
|
route.Dest.String(), ifName)
|
||||||
if gw != "" {
|
if gw != "" {
|
||||||
cmd += " nexthop=" + gw
|
cmd += " nexthop=" + gw
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user