Skip to content

Commit 7a10607

Browse files
author
null
committed
winroute
1 parent d2758a0 commit 7a10607

8 files changed

Lines changed: 93 additions & 15 deletions

File tree

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ require (
2727
golang.org/x/sys v0.42.0
2828
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2
2929
golang.zx2c4.com/wireguard v0.0.0-20250521234502-f333402bd9cb
30+
golang.zx2c4.com/wireguard/windows v0.5.3
3031
google.golang.org/grpc v1.79.3
3132
google.golang.org/protobuf v1.36.11
3233
gvisor.dev/gvisor v0.0.0-20260122175437-89a5d21be8f0

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,8 @@ golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 h1:B82qJJgjvYKsXS9jeu
131131
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI=
132132
golang.zx2c4.com/wireguard v0.0.0-20250521234502-f333402bd9cb h1:whnFRlWMcXI9d+ZbWg+4sHnLp52d5yiIPUxMBSt4X9A=
133133
golang.zx2c4.com/wireguard v0.0.0-20250521234502-f333402bd9cb/go.mod h1:rpwXGsirqLqN2L0JDJQlwOboGHmptD5ZD6T2VmcqhTw=
134+
golang.zx2c4.com/wireguard/windows v0.5.3 h1:On6j2Rpn3OEMXqBq00QEDC7bWSZrPIHKIus8eIuExIE=
135+
golang.zx2c4.com/wireguard/windows v0.5.3/go.mod h1:9TEe8TJmtwyQebdFwAkEWOPr3prrtqm+REGFifP60hI=
134136
gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
135137
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
136138
google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217 h1:gRkg/vSppuSQoDjxyiGfN4Upv/h/DQmIR10ZU8dh4Ww=

infra/conf/tun.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,18 @@ import (
66
)
77

88
type TunConfig struct {
9-
Name string `json:"name"`
10-
MTU uint32 `json:"MTU"`
11-
UserLevel uint32 `json:"userLevel"`
9+
Name string `json:"name"`
10+
MTU uint32 `json:"MTU"`
11+
UserLevel uint32 `json:"userLevel"`
12+
WinRoute []string `json:"winRoute"`
1213
}
1314

1415
func (v *TunConfig) Build() (proto.Message, error) {
1516
config := &tun.Config{
1617
Name: v.Name,
1718
MTU: v.MTU,
1819
UserLevel: v.UserLevel,
20+
WinRoute: v.WinRoute,
1921
}
2022

2123
if v.Name == "" {

proxy/tun/config.pb.go

Lines changed: 11 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

proxy/tun/config.proto

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,5 @@ message Config {
1010
string name = 1;
1111
uint32 MTU = 2;
1212
uint32 user_level = 3;
13+
repeated string win_route = 4;
1314
}

proxy/tun/handler.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,9 @@ func (t *Handler) Init(ctx context.Context, pm policy.Manager, dispatcher routin
6060

6161
tunName := t.config.Name
6262
tunOptions := TunOptions{
63-
Name: tunName,
64-
MTU: t.config.MTU,
63+
Name: tunName,
64+
MTU: t.config.MTU,
65+
WinRoute: t.config.WinRoute,
6566
}
6667
tunInterface, err := NewTun(tunOptions)
6768
if err != nil {

proxy/tun/tun.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ type Tun interface {
88

99
// TunOptions for tun interface implementation
1010
type TunOptions struct {
11-
Name string
12-
MTU uint32
11+
Name string
12+
MTU uint32
13+
WinRoute []string
1314
}

proxy/tun/tun_windows.go

Lines changed: 67 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,12 @@ package tun
55
import (
66
"crypto/md5"
77
"errors"
8+
"net/netip"
89
"unsafe"
910

1011
"golang.org/x/sys/windows"
1112
"golang.zx2c4.com/wintun"
13+
"golang.zx2c4.com/wireguard/windows/tunnel/winipcfg"
1214
"gvisor.dev/gvisor/pkg/buffer"
1315
"gvisor.dev/gvisor/pkg/tcpip"
1416
"gvisor.dev/gvisor/pkg/tcpip/stack"
@@ -70,20 +72,79 @@ func open(name string) (*wintun.Adapter, error) {
7072
// generate a deterministic GUID from the adapter name
7173
id := md5.Sum([]byte(name))
7274
guid := (*windows.GUID)(unsafe.Pointer(&id[0]))
73-
// try to open existing adapter by name
74-
adapter, err := wintun.OpenAdapter(name)
75-
if err == nil {
76-
return adapter, nil
77-
}
7875
// try to create adapter anew
79-
adapter, err = wintun.CreateAdapter(name, "Xray", guid)
76+
adapter, err := wintun.CreateAdapter(name, "Xray", guid)
8077
if err == nil {
8178
return adapter, nil
8279
}
8380
return nil, err
8481
}
8582

8683
func (t *WindowsTun) Start() error {
84+
var has4, has6 bool
85+
allowedIPs := make([]netip.Prefix, 0, len(t.options.WinRoute))
86+
for _, route := range t.options.WinRoute {
87+
allowedIPs = append(allowedIPs, netip.MustParsePrefix(route))
88+
}
89+
routesMap := make(map[winipcfg.RouteData]struct{})
90+
for _, ip := range allowedIPs {
91+
route := winipcfg.RouteData{
92+
Destination: ip.Masked(),
93+
Metric: 0,
94+
}
95+
if ip.Addr().Is4() {
96+
has4 = true
97+
route.NextHop = netip.IPv4Unspecified()
98+
} else {
99+
has6 = true
100+
route.NextHop = netip.IPv6Unspecified()
101+
}
102+
routesMap[route] = struct{}{}
103+
}
104+
routesData := make([]*winipcfg.RouteData, 0, len(routesMap))
105+
for route := range routesMap {
106+
r := route
107+
routesData = append(routesData, &r)
108+
}
109+
luid := winipcfg.LUID(t.adapter.LUID())
110+
err := luid.SetRoutes(routesData)
111+
if err != nil {
112+
return err
113+
}
114+
if has4 {
115+
ipif, err := luid.IPInterface(windows.AF_INET)
116+
if err != nil {
117+
return err
118+
}
119+
ipif.RouterDiscoveryBehavior = winipcfg.RouterDiscoveryDisabled
120+
ipif.DadTransmits = 0
121+
ipif.ManagedAddressConfigurationSupported = false
122+
ipif.OtherStatefulConfigurationSupported = false
123+
ipif.NLMTU = t.options.MTU
124+
ipif.UseAutomaticMetric = false
125+
ipif.Metric = 0
126+
err = ipif.Set()
127+
if err != nil {
128+
return err
129+
}
130+
}
131+
if has6 {
132+
ipif, err := luid.IPInterface(windows.AF_INET6)
133+
if err != nil {
134+
return err
135+
}
136+
ipif.RouterDiscoveryBehavior = winipcfg.RouterDiscoveryDisabled
137+
ipif.DadTransmits = 0
138+
ipif.ManagedAddressConfigurationSupported = false
139+
ipif.OtherStatefulConfigurationSupported = false
140+
ipif.NLMTU = t.options.MTU
141+
ipif.UseAutomaticMetric = false
142+
ipif.Metric = 0
143+
err = ipif.Set()
144+
if err != nil {
145+
return err
146+
}
147+
}
87148
return nil
88149
}
89150

0 commit comments

Comments
 (0)