add vtun listener and handler
This commit is contained in:
@@ -1,14 +1,14 @@
|
|||||||
module github.com/go-gost/x
|
module github.com/go-gost/x
|
||||||
|
|
||||||
go 1.23.0
|
go 1.23.1
|
||||||
|
|
||||||
toolchain go1.24.4
|
toolchain go1.24.5
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137
|
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137
|
||||||
github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d
|
github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d
|
||||||
github.com/gin-contrib/cors v1.7.2
|
github.com/gin-contrib/cors v1.7.2
|
||||||
github.com/gin-gonic/gin v1.10.0
|
github.com/gin-gonic/gin v1.10.1
|
||||||
github.com/go-gost/core v0.3.2
|
github.com/go-gost/core v0.3.2
|
||||||
github.com/go-gost/gosocks4 v0.0.1
|
github.com/go-gost/gosocks4 v0.0.1
|
||||||
github.com/go-gost/gosocks5 v0.4.2
|
github.com/go-gost/gosocks5 v0.4.2
|
||||||
@@ -30,29 +30,32 @@ require (
|
|||||||
github.com/quic-go/webtransport-go v0.9.0
|
github.com/quic-go/webtransport-go v0.9.0
|
||||||
github.com/rs/xid v1.3.0
|
github.com/rs/xid v1.3.0
|
||||||
github.com/shadowsocks/go-shadowsocks2 v0.1.6-0.20241020092332-e1fe9ea73740
|
github.com/shadowsocks/go-shadowsocks2 v0.1.6-0.20241020092332-e1fe9ea73740
|
||||||
github.com/sirupsen/logrus v1.8.1
|
github.com/sirupsen/logrus v1.9.3
|
||||||
github.com/songgao/water v0.0.0-20200317203138-2b4b6d7c09d8
|
github.com/songgao/water v0.0.0-20200317203138-2b4b6d7c09d8
|
||||||
github.com/spf13/viper v1.19.0
|
github.com/spf13/viper v1.19.0
|
||||||
github.com/stretchr/testify v1.9.0
|
github.com/stretchr/testify v1.9.0
|
||||||
github.com/vishvananda/netlink v1.1.0
|
github.com/vishvananda/netlink v1.1.1-0.20211118161826-650dca95af54
|
||||||
github.com/vishvananda/netns v0.0.4
|
github.com/vishvananda/netns v0.0.4
|
||||||
github.com/vulcand/predicate v1.2.0
|
github.com/vulcand/predicate v1.2.0
|
||||||
|
github.com/xjasonlyu/tun2socks/v2 v2.6.0
|
||||||
github.com/xtaci/kcp-go/v5 v5.6.5
|
github.com/xtaci/kcp-go/v5 v5.6.5
|
||||||
github.com/xtaci/smux v1.5.31
|
github.com/xtaci/smux v1.5.31
|
||||||
github.com/xtaci/tcpraw v1.2.25
|
github.com/xtaci/tcpraw v1.2.25
|
||||||
github.com/yl2chen/cidranger v1.0.2
|
github.com/yl2chen/cidranger v1.0.2
|
||||||
github.com/zalando/go-keyring v0.2.4
|
github.com/zalando/go-keyring v0.2.4
|
||||||
golang.org/x/crypto v0.39.0
|
go.uber.org/atomic v1.11.0
|
||||||
|
golang.org/x/crypto v0.40.0
|
||||||
golang.org/x/exp v0.0.0-20241210194714-1829a127f884
|
golang.org/x/exp v0.0.0-20241210194714-1829a127f884
|
||||||
golang.org/x/net v0.40.0
|
golang.org/x/net v0.42.0
|
||||||
golang.org/x/sys v0.33.0
|
golang.org/x/sys v0.34.0
|
||||||
golang.org/x/text v0.26.0
|
golang.org/x/text v0.27.0
|
||||||
golang.org/x/time v0.5.0
|
golang.org/x/time v0.11.0
|
||||||
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173
|
golang.zx2c4.com/wireguard v0.0.0-20250521234502-f333402bd9cb
|
||||||
google.golang.org/grpc v1.67.1
|
google.golang.org/grpc v1.67.1
|
||||||
google.golang.org/protobuf v1.35.1
|
google.golang.org/protobuf v1.35.1
|
||||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1
|
gopkg.in/natefinch/lumberjack.v2 v2.2.1
|
||||||
gopkg.in/yaml.v3 v3.0.1
|
gopkg.in/yaml.v3 v3.0.1
|
||||||
|
gvisor.dev/gvisor v0.0.0-20250523182742-eede7a881b20
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
@@ -75,6 +78,7 @@ require (
|
|||||||
github.com/go-playground/validator/v10 v10.20.0 // indirect
|
github.com/go-playground/validator/v10 v10.20.0 // indirect
|
||||||
github.com/goccy/go-json v0.10.2 // indirect
|
github.com/goccy/go-json v0.10.2 // indirect
|
||||||
github.com/godbus/dbus/v5 v5.1.0 // indirect
|
github.com/godbus/dbus/v5 v5.1.0 // indirect
|
||||||
|
github.com/google/btree v1.1.3 // indirect
|
||||||
github.com/google/gopacket v1.1.19 // indirect
|
github.com/google/gopacket v1.1.19 // indirect
|
||||||
github.com/gravitational/trace v1.1.16-0.20220114165159-14a9a7dd6aaf // indirect
|
github.com/gravitational/trace v1.1.16-0.20220114165159-14a9a7dd6aaf // indirect
|
||||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||||
@@ -116,10 +120,12 @@ require (
|
|||||||
go.uber.org/multierr v1.11.0 // indirect
|
go.uber.org/multierr v1.11.0 // indirect
|
||||||
golang.org/x/arch v0.8.0 // indirect
|
golang.org/x/arch v0.8.0 // indirect
|
||||||
golang.org/x/mod v0.25.0 // indirect
|
golang.org/x/mod v0.25.0 // indirect
|
||||||
golang.org/x/sync v0.15.0 // indirect
|
golang.org/x/sync v0.16.0 // indirect
|
||||||
golang.org/x/term v0.32.0 // indirect
|
golang.org/x/term v0.33.0 // indirect
|
||||||
golang.org/x/tools v0.33.0 // indirect
|
golang.org/x/tools v0.34.0 // indirect
|
||||||
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
|
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect
|
||||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||||
)
|
)
|
||||||
|
|
||||||
|
replace github.com/ugorji/go v1.1.4 => github.com/ugorji/go/codec v1.2.12
|
||||||
|
|||||||
@@ -47,8 +47,8 @@ github.com/gin-contrib/cors v1.7.2 h1:oLDHxdg8W/XDoN/8zamqk/Drgt4oVZDvaV0YmvVICQ
|
|||||||
github.com/gin-contrib/cors v1.7.2/go.mod h1:SUJVARKgQ40dmrzgXEVxj2m7Ig1v1qIboQkPDTQ9t2E=
|
github.com/gin-contrib/cors v1.7.2/go.mod h1:SUJVARKgQ40dmrzgXEVxj2m7Ig1v1qIboQkPDTQ9t2E=
|
||||||
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
|
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
|
||||||
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
||||||
github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU=
|
github.com/gin-gonic/gin v1.10.1 h1:T0ujvqyCSqRopADpgPgiTT63DUQVSfojyME59Ei63pQ=
|
||||||
github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
|
github.com/gin-gonic/gin v1.10.1/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
|
||||||
github.com/go-gost/core v0.3.2 h1:AjmIYWVa5fc172zIupT3e1pdnKx76LxppGiw00uRsSA=
|
github.com/go-gost/core v0.3.2 h1:AjmIYWVa5fc172zIupT3e1pdnKx76LxppGiw00uRsSA=
|
||||||
github.com/go-gost/core v0.3.2/go.mod h1:WGI43jOka7FAsSAwi/fSMaqxdR+E339ycb4NBGlFr6A=
|
github.com/go-gost/core v0.3.2/go.mod h1:WGI43jOka7FAsSAwi/fSMaqxdR+E339ycb4NBGlFr6A=
|
||||||
github.com/go-gost/gosocks4 v0.0.1 h1:+k1sec8HlELuQV7rWftIkmy8UijzUt2I6t+iMPlGB2s=
|
github.com/go-gost/gosocks4 v0.0.1 h1:+k1sec8HlELuQV7rWftIkmy8UijzUt2I6t+iMPlGB2s=
|
||||||
@@ -90,8 +90,8 @@ github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvq
|
|||||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||||
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
|
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
|
||||||
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||||
github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4=
|
github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg=
|
||||||
github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA=
|
github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
|
||||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
@@ -193,8 +193,8 @@ github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWR
|
|||||||
github.com/shadowsocks/go-shadowsocks2 v0.1.6-0.20241020092332-e1fe9ea73740 h1:XdDrN8rtxdgW3TLn7pAuobI9PhPMbf6Geu9nvFzXn2E=
|
github.com/shadowsocks/go-shadowsocks2 v0.1.6-0.20241020092332-e1fe9ea73740 h1:XdDrN8rtxdgW3TLn7pAuobI9PhPMbf6Geu9nvFzXn2E=
|
||||||
github.com/shadowsocks/go-shadowsocks2 v0.1.6-0.20241020092332-e1fe9ea73740/go.mod h1:Oqfn/ykzqjeX00+7IuPyR7wGYgOzld0Tni6djgElacI=
|
github.com/shadowsocks/go-shadowsocks2 v0.1.6-0.20241020092332-e1fe9ea73740/go.mod h1:Oqfn/ykzqjeX00+7IuPyR7wGYgOzld0Tni6djgElacI=
|
||||||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||||
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
|
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||||
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||||
github.com/songgao/water v0.0.0-20200317203138-2b4b6d7c09d8 h1:TG/diQgUe0pntT/2D9tmUCz4VNwm9MfrtPr0SU2qSX8=
|
github.com/songgao/water v0.0.0-20200317203138-2b4b6d7c09d8 h1:TG/diQgUe0pntT/2D9tmUCz4VNwm9MfrtPr0SU2qSX8=
|
||||||
github.com/songgao/water v0.0.0-20200317203138-2b4b6d7c09d8/go.mod h1:P5HUIBuIWKbyjl083/loAegFkfbFNx5i2qEP4CNbm7E=
|
github.com/songgao/water v0.0.0-20200317203138-2b4b6d7c09d8/go.mod h1:P5HUIBuIWKbyjl083/loAegFkfbFNx5i2qEP4CNbm7E=
|
||||||
github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
|
github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
|
||||||
@@ -235,13 +235,15 @@ github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS
|
|||||||
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
|
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
|
||||||
github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
|
github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
|
||||||
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
||||||
github.com/vishvananda/netlink v1.1.0 h1:1iyaYNBLmP6L0220aDnYQpo1QEV4t4hJ+xEEhhJH8j0=
|
github.com/vishvananda/netlink v1.1.1-0.20211118161826-650dca95af54 h1:8mhqcHPqTMhSPoslhGYihEgSfc77+7La1P6kiB6+9So=
|
||||||
github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE=
|
github.com/vishvananda/netlink v1.1.1-0.20211118161826-650dca95af54/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho=
|
||||||
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU=
|
github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
|
||||||
github.com/vishvananda/netns v0.0.4 h1:Oeaw1EM2JMxD51g9uhtC0D7erkIjgmj8+JZc26m1YX8=
|
github.com/vishvananda/netns v0.0.4 h1:Oeaw1EM2JMxD51g9uhtC0D7erkIjgmj8+JZc26m1YX8=
|
||||||
github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM=
|
github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM=
|
||||||
github.com/vulcand/predicate v1.2.0 h1:uFsW1gcnnR7R+QTID+FVcs0sSYlIGntoGOTb3rQJt50=
|
github.com/vulcand/predicate v1.2.0 h1:uFsW1gcnnR7R+QTID+FVcs0sSYlIGntoGOTb3rQJt50=
|
||||||
github.com/vulcand/predicate v1.2.0/go.mod h1:VipoNYXny6c8N381zGUWkjuuNHiRbeAZhE7Qm9c+2GA=
|
github.com/vulcand/predicate v1.2.0/go.mod h1:VipoNYXny6c8N381zGUWkjuuNHiRbeAZhE7Qm9c+2GA=
|
||||||
|
github.com/xjasonlyu/tun2socks/v2 v2.6.0 h1:gI9saJT3XgH4e6v9jBuHRLwK7l3aN9YFWec/SsDTDx4=
|
||||||
|
github.com/xjasonlyu/tun2socks/v2 v2.6.0/go.mod h1:35AwqxIxnMkfBfT0UJ1Lku7PZm2ZiZJ8sxHyp0gt1yw=
|
||||||
github.com/xtaci/kcp-go/v5 v5.6.5 h1:oxGZNobj3OddrLzwdJYnR/waNgwrL98u02u0DWNHE3k=
|
github.com/xtaci/kcp-go/v5 v5.6.5 h1:oxGZNobj3OddrLzwdJYnR/waNgwrL98u02u0DWNHE3k=
|
||||||
github.com/xtaci/kcp-go/v5 v5.6.5/go.mod h1:Qy3Zf2tWTdFdEs0E8JvhrX+39r5UDZoYac8anvud7/Q=
|
github.com/xtaci/kcp-go/v5 v5.6.5/go.mod h1:Qy3Zf2tWTdFdEs0E8JvhrX+39r5UDZoYac8anvud7/Q=
|
||||||
github.com/xtaci/lossyconn v0.0.0-20190602105132-8df528c0c9ae h1:J0GxkO96kL4WF+AIT3M4mfUVinOCPgf2uUWYFUzN0sM=
|
github.com/xtaci/lossyconn v0.0.0-20190602105132-8df528c0c9ae h1:J0GxkO96kL4WF+AIT3M4mfUVinOCPgf2uUWYFUzN0sM=
|
||||||
@@ -255,6 +257,8 @@ github.com/yl2chen/cidranger v1.0.2/go.mod h1:9U1yz7WPYDwf0vpNWFaeRh0bjwz5RVgRy/
|
|||||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||||
github.com/zalando/go-keyring v0.2.4 h1:wi2xxTqdiwMKbM6TWwi+uJCG/Tum2UV0jqaQhCa9/68=
|
github.com/zalando/go-keyring v0.2.4 h1:wi2xxTqdiwMKbM6TWwi+uJCG/Tum2UV0jqaQhCa9/68=
|
||||||
github.com/zalando/go-keyring v0.2.4/go.mod h1:HL4k+OXQfJUWaMnqyuSOc0drfGPX2b51Du6K+MRgZMk=
|
github.com/zalando/go-keyring v0.2.4/go.mod h1:HL4k+OXQfJUWaMnqyuSOc0drfGPX2b51Du6K+MRgZMk=
|
||||||
|
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
|
||||||
|
go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
|
||||||
go.uber.org/mock v0.5.0 h1:KAMbZvZPyBPWgD14IrIQ38QCyjwpvVVV6K/bHl1IwQU=
|
go.uber.org/mock v0.5.0 h1:KAMbZvZPyBPWgD14IrIQ38QCyjwpvVVV6K/bHl1IwQU=
|
||||||
go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM=
|
go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM=
|
||||||
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
||||||
@@ -269,8 +273,8 @@ golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee/go.mod h1:LzIPMQfyMNhhGPh
|
|||||||
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU=
|
golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU=
|
||||||
golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM=
|
golang.org/x/crypto v0.40.0 h1:r4x+VvoG5Fm+eJcxMaY8CQM7Lb0l1lsmjGBQ6s8BfKM=
|
||||||
golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U=
|
golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY=
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/exp v0.0.0-20241210194714-1829a127f884 h1:Y/Mj/94zIQQGHVSv1tTtQBDaQaJe62U9bkDZKKyhPCU=
|
golang.org/x/exp v0.0.0-20241210194714-1829a127f884 h1:Y/Mj/94zIQQGHVSv1tTtQBDaQaJe62U9bkDZKKyhPCU=
|
||||||
golang.org/x/exp v0.0.0-20241210194714-1829a127f884/go.mod h1:qj5a5QZpwLU2NLQudwIN5koi3beDhSAlJwa67PuM98c=
|
golang.org/x/exp v0.0.0-20241210194714-1829a127f884/go.mod h1:qj5a5QZpwLU2NLQudwIN5koi3beDhSAlJwa67PuM98c=
|
||||||
@@ -294,45 +298,47 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v
|
|||||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws=
|
golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws=
|
||||||
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||||
golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
|
golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs=
|
||||||
golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
|
golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8=
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8=
|
golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
|
||||||
golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
|
golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA=
|
||||||
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ=
|
golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ=
|
||||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||||
golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg=
|
golang.org/x/term v0.33.0 h1:NuFncQrRcaRvVmgRkvM3j/F00gWIAlcmlB8ACEKmGIg=
|
||||||
golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ=
|
golang.org/x/term v0.33.0/go.mod h1:s18+ql9tYWp1IfpV9DmCtQDDSRBUjKaw9M1eAv5UeF0=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M=
|
golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4=
|
||||||
golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA=
|
golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU=
|
||||||
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
|
golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0=
|
||||||
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||||
@@ -341,15 +347,15 @@ golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBn
|
|||||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||||
golang.org/x/tools v0.33.0 h1:4qz2S3zmRxbGIhDIAgjxvFutSvH5EfnsYrRBj0UI0bc=
|
golang.org/x/tools v0.34.0 h1:qIpSLOxeCYGg9TrcJokLBG4KFA6d795g0xkBkiESGlo=
|
||||||
golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI=
|
golang.org/x/tools v0.34.0/go.mod h1:pAP9OwEaY1CAW3HOmg3hLZC5Z0CCmzjAF2UQMSqNARg=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 h1:B82qJJgjvYKsXS9jeunTOisW56dUokqW/FOteYJJ/yg=
|
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 h1:B82qJJgjvYKsXS9jeunTOisW56dUokqW/FOteYJJ/yg=
|
||||||
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI=
|
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI=
|
||||||
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173 h1:/jFs0duh4rdb8uIfPMv78iAJGcPKDeqAFnaLBropIC4=
|
golang.zx2c4.com/wireguard v0.0.0-20250521234502-f333402bd9cb h1:whnFRlWMcXI9d+ZbWg+4sHnLp52d5yiIPUxMBSt4X9A=
|
||||||
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173/go.mod h1:tkCQ4FQXmpAgYVh++1cq16/dH4QJtmvpRv19DWGAHSA=
|
golang.zx2c4.com/wireguard v0.0.0-20250521234502-f333402bd9cb/go.mod h1:rpwXGsirqLqN2L0JDJQlwOboGHmptD5ZD6T2VmcqhTw=
|
||||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||||
@@ -384,8 +390,8 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gvisor.dev/gvisor v0.0.0-20230927004350-cbd86285d259 h1:TbRPT0HtzFP3Cno1zZo7yPzEEnfu8EjLfl6IU9VfqkQ=
|
gvisor.dev/gvisor v0.0.0-20250523182742-eede7a881b20 h1:0DxLu8hxI1OGp1qVRPqNd+2k1a7hMNUNqbZG0IrtKlM=
|
||||||
gvisor.dev/gvisor v0.0.0-20230927004350-cbd86285d259/go.mod h1:AVgIgHMwK63XvmAzWG9vLQ41YnVHN0du0tEC46fI7yY=
|
gvisor.dev/gvisor v0.0.0-20250523182742-eede7a881b20/go.mod h1:3r5CMtNQMKIvBlrmM9xWUNamjKBYPOWyXOjmg5Kts3g=
|
||||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
|
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
|
||||||
|
|||||||
@@ -0,0 +1,161 @@
|
|||||||
|
// Package iobased provides the implementation of io.ReadWriter
|
||||||
|
// based data-link layer endpoints.
|
||||||
|
package tun
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"io"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/go-gost/core/logger"
|
||||||
|
"gvisor.dev/gvisor/pkg/buffer"
|
||||||
|
"gvisor.dev/gvisor/pkg/tcpip"
|
||||||
|
"gvisor.dev/gvisor/pkg/tcpip/header"
|
||||||
|
"gvisor.dev/gvisor/pkg/tcpip/link/channel"
|
||||||
|
"gvisor.dev/gvisor/pkg/tcpip/stack"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Queue length for outbound packet, arriving for read. Overflow
|
||||||
|
// causes packet drops.
|
||||||
|
defaultOutQueueLen = 1 << 10
|
||||||
|
)
|
||||||
|
|
||||||
|
// Endpoint implements the interface of stack.LinkEndpoint from io.ReadWriter.
|
||||||
|
type Endpoint struct {
|
||||||
|
*channel.Endpoint
|
||||||
|
|
||||||
|
// rw is the io.ReadWriter for reading and writing packets.
|
||||||
|
rw io.ReadWriter
|
||||||
|
|
||||||
|
// mtu (maximum transmission unit) is the maximum size of a packet.
|
||||||
|
mtu uint32
|
||||||
|
|
||||||
|
// offset can be useful when perform TUN device I/O with TUN_PI enabled.
|
||||||
|
offset int
|
||||||
|
|
||||||
|
// once is used to perform the init action once when attaching.
|
||||||
|
once sync.Once
|
||||||
|
|
||||||
|
// wg keeps track of running goroutines.
|
||||||
|
wg sync.WaitGroup
|
||||||
|
|
||||||
|
log logger.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
// New returns stack.LinkEndpoint(.*Endpoint) and error.
|
||||||
|
func newEndpoint(rw io.ReadWriter, mtu uint32, offset int, log logger.Logger) (*Endpoint, error) {
|
||||||
|
if mtu == 0 {
|
||||||
|
return nil, errors.New("MTU size is zero")
|
||||||
|
}
|
||||||
|
|
||||||
|
if rw == nil {
|
||||||
|
return nil, errors.New("RW interface is nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
if offset < 0 {
|
||||||
|
return nil, errors.New("offset must be non-negative")
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Endpoint{
|
||||||
|
Endpoint: channel.New(defaultOutQueueLen, mtu, ""),
|
||||||
|
rw: rw,
|
||||||
|
mtu: mtu,
|
||||||
|
offset: offset,
|
||||||
|
log: log,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attach launches the goroutine that reads packets from io.Reader and
|
||||||
|
// dispatches them via the provided dispatcher.
|
||||||
|
func (e *Endpoint) Attach(dispatcher stack.NetworkDispatcher) {
|
||||||
|
e.Endpoint.Attach(dispatcher)
|
||||||
|
e.once.Do(func() {
|
||||||
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
|
e.wg.Add(2)
|
||||||
|
go func() {
|
||||||
|
e.outboundLoop(ctx)
|
||||||
|
e.wg.Done()
|
||||||
|
}()
|
||||||
|
go func() {
|
||||||
|
e.dispatchLoop(cancel)
|
||||||
|
e.wg.Done()
|
||||||
|
}()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *Endpoint) Wait() {
|
||||||
|
e.wg.Wait()
|
||||||
|
}
|
||||||
|
|
||||||
|
// dispatchLoop dispatches packets to upper layer.
|
||||||
|
func (e *Endpoint) dispatchLoop(cancel context.CancelFunc) {
|
||||||
|
// Call cancel() to ensure (*Endpoint).outboundLoop(context.Context) exits
|
||||||
|
// gracefully after (*Endpoint).dispatchLoop(context.CancelFunc) returns.
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
offset, mtu := e.offset, int(e.mtu)
|
||||||
|
|
||||||
|
for {
|
||||||
|
data := make([]byte, offset+mtu)
|
||||||
|
|
||||||
|
n, err := e.rw.Read(data)
|
||||||
|
if err != nil {
|
||||||
|
e.log.Error(err)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
e.log.Debugf("read tun: (%d) % x", n, data[:n])
|
||||||
|
|
||||||
|
if n == 0 || n > mtu {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if !e.IsAttached() {
|
||||||
|
continue /* unattached, drop packet */
|
||||||
|
}
|
||||||
|
|
||||||
|
pkt := stack.NewPacketBuffer(stack.PacketBufferOptions{
|
||||||
|
Payload: buffer.MakeWithData(data[offset : offset+n]),
|
||||||
|
})
|
||||||
|
|
||||||
|
switch header.IPVersion(data[offset:]) {
|
||||||
|
case header.IPv4Version:
|
||||||
|
e.InjectInbound(header.IPv4ProtocolNumber, pkt)
|
||||||
|
case header.IPv6Version:
|
||||||
|
e.InjectInbound(header.IPv6ProtocolNumber, pkt)
|
||||||
|
}
|
||||||
|
pkt.DecRef()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// outboundLoop reads outbound packets from channel, and then it calls
|
||||||
|
// writePacket to send those packets back to lower layer.
|
||||||
|
func (e *Endpoint) outboundLoop(ctx context.Context) {
|
||||||
|
for {
|
||||||
|
pkt := e.ReadContext(ctx)
|
||||||
|
if pkt == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
e.writePacket(pkt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// writePacket writes outbound packets to the io.Writer.
|
||||||
|
func (e *Endpoint) writePacket(pkt *stack.PacketBuffer) tcpip.Error {
|
||||||
|
defer pkt.DecRef()
|
||||||
|
|
||||||
|
buf := pkt.ToBuffer()
|
||||||
|
defer buf.Release()
|
||||||
|
if e.offset != 0 {
|
||||||
|
v := buffer.NewViewWithData(make([]byte, e.offset))
|
||||||
|
_ = buf.Prepend(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := e.rw.Write(buf.Flatten()); err != nil {
|
||||||
|
return &tcpip.ErrInvalidEndpointState{}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
package tun
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/go-gost/core/handler"
|
||||||
|
md "github.com/go-gost/core/metadata"
|
||||||
|
ctxvalue "github.com/go-gost/x/ctx"
|
||||||
|
"github.com/go-gost/x/registry"
|
||||||
|
"github.com/xjasonlyu/tun2socks/v2/core"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
registry.HandlerRegistry().Register("vtun", NewHandler)
|
||||||
|
}
|
||||||
|
|
||||||
|
type tunHandler struct {
|
||||||
|
options handler.Options
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewHandler(opts ...handler.Option) handler.Handler {
|
||||||
|
options := handler.Options{}
|
||||||
|
for _, opt := range opts {
|
||||||
|
opt(&options)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &tunHandler{
|
||||||
|
options: options,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *tunHandler) Init(md md.Metadata) (err error) {
|
||||||
|
if err = h.parseMetadata(md); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *tunHandler) Handle(ctx context.Context, conn net.Conn, opts ...handler.HandleOption) error {
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
log := h.options.Logger
|
||||||
|
|
||||||
|
start := time.Now()
|
||||||
|
log = log.WithFields(map[string]any{
|
||||||
|
"remote": conn.RemoteAddr().String(),
|
||||||
|
"local": conn.LocalAddr().String(),
|
||||||
|
"sid": ctxvalue.SidFromContext(ctx),
|
||||||
|
})
|
||||||
|
|
||||||
|
log.Infof("%s <> %s", conn.RemoteAddr(), conn.LocalAddr())
|
||||||
|
defer func() {
|
||||||
|
log.WithFields(map[string]any{
|
||||||
|
"duration": time.Since(start),
|
||||||
|
}).Infof("%s >< %s", conn.RemoteAddr(), conn.LocalAddr())
|
||||||
|
}()
|
||||||
|
|
||||||
|
ep, err := newEndpoint(conn, 1420, 0, log)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
th := newTransportHandler(log)
|
||||||
|
th.ProcessAsync()
|
||||||
|
defer th.Close()
|
||||||
|
|
||||||
|
stack, err := core.CreateStack(&core.Config{
|
||||||
|
LinkEndpoint: ep,
|
||||||
|
TransportHandler: th,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer stack.Close()
|
||||||
|
|
||||||
|
log.Debugf("is attached: %v", ep.IsAttached())
|
||||||
|
|
||||||
|
<-ctx.Done()
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package tun
|
||||||
|
|
||||||
|
import (
|
||||||
|
mdata "github.com/go-gost/core/metadata"
|
||||||
|
)
|
||||||
|
|
||||||
|
type metadata struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *tunHandler) parseMetadata(md mdata.Metadata) (err error) {
|
||||||
|
return
|
||||||
|
}
|
||||||
@@ -0,0 +1,105 @@
|
|||||||
|
package tun
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net/netip"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/go-gost/core/logger"
|
||||||
|
"github.com/xjasonlyu/tun2socks/v2/core/adapter"
|
||||||
|
"go.uber.org/atomic"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// tcpConnectTimeout is the default timeout for TCP handshakes.
|
||||||
|
tcpConnectTimeout = 5 * time.Second
|
||||||
|
// tcpWaitTimeout implements a TCP half-close timeout.
|
||||||
|
tcpWaitTimeout = 60 * time.Second
|
||||||
|
// udpSessionTimeout is the default timeout for UDP sessions.
|
||||||
|
udpSessionTimeout = 60 * time.Second
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ adapter.TransportHandler = (*transportHandler)(nil)
|
||||||
|
|
||||||
|
type transportHandler struct {
|
||||||
|
// Unbuffered TCP/UDP queues.
|
||||||
|
tcpQueue chan adapter.TCPConn
|
||||||
|
udpQueue chan adapter.UDPConn
|
||||||
|
|
||||||
|
// UDP session timeout.
|
||||||
|
udpTimeout *atomic.Duration
|
||||||
|
|
||||||
|
procOnce sync.Once
|
||||||
|
procCancel context.CancelFunc
|
||||||
|
|
||||||
|
log logger.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func newTransportHandler(log logger.Logger) *transportHandler {
|
||||||
|
return &transportHandler{
|
||||||
|
tcpQueue: make(chan adapter.TCPConn),
|
||||||
|
udpQueue: make(chan adapter.UDPConn),
|
||||||
|
udpTimeout: atomic.NewDuration(udpSessionTimeout),
|
||||||
|
procCancel: func() { /* nop */ },
|
||||||
|
log: log,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *transportHandler) HandleTCP(conn adapter.TCPConn) {
|
||||||
|
t.tcpQueue <- conn
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *transportHandler) HandleUDP(conn adapter.UDPConn) {
|
||||||
|
t.udpQueue <- conn
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *transportHandler) process(ctx context.Context) {
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case conn := <-t.tcpQueue:
|
||||||
|
go t.handleTCPConn(conn)
|
||||||
|
case conn := <-t.udpQueue:
|
||||||
|
go t.handleUDPConn(conn)
|
||||||
|
case <-ctx.Done():
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ProcessAsync can be safely called multiple times, but will only be effective once.
|
||||||
|
func (t *transportHandler) ProcessAsync() {
|
||||||
|
t.procOnce.Do(func() {
|
||||||
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
|
t.procCancel = cancel
|
||||||
|
go t.process(ctx)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close closes the Tunnel and releases its resources.
|
||||||
|
func (t *transportHandler) Close() {
|
||||||
|
t.procCancel()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *transportHandler) SetUDPTimeout(timeout time.Duration) {
|
||||||
|
t.udpTimeout.Store(timeout)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *transportHandler) handleTCPConn(originConn adapter.TCPConn) {
|
||||||
|
defer originConn.Close()
|
||||||
|
|
||||||
|
id := originConn.ID()
|
||||||
|
|
||||||
|
srcIP, _ := netip.AddrFromSlice(id.RemoteAddress.AsSlice())
|
||||||
|
dstIP, _ := netip.AddrFromSlice(id.LocalAddress.AsSlice())
|
||||||
|
|
||||||
|
raddr := netip.AddrPortFrom(srcIP, id.RemotePort)
|
||||||
|
laddr := netip.AddrPortFrom(dstIP, id.LocalPort)
|
||||||
|
|
||||||
|
t.log.Debugf("[TCP] %s <-> %s", raddr.String(), laddr.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Port Restricted NAT support.
|
||||||
|
func (t *transportHandler) handleUDPConn(uc adapter.UDPConn) {
|
||||||
|
defer uc.Close()
|
||||||
|
}
|
||||||
@@ -27,7 +27,7 @@ type tunListener struct {
|
|||||||
addr net.Addr
|
addr net.Addr
|
||||||
cqueue chan net.Conn
|
cqueue chan net.Conn
|
||||||
closed chan struct{}
|
closed chan struct{}
|
||||||
logger logger.Logger
|
log logger.Logger
|
||||||
md metadata
|
md metadata
|
||||||
options listener.Options
|
options listener.Options
|
||||||
routes []*router.Route
|
routes []*router.Route
|
||||||
@@ -39,7 +39,7 @@ func NewListener(opts ...listener.Option) listener.Listener {
|
|||||||
opt(&options)
|
opt(&options)
|
||||||
}
|
}
|
||||||
return &tunListener{
|
return &tunListener{
|
||||||
logger: options.Logger,
|
log: options.Logger,
|
||||||
options: options,
|
options: options,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -83,7 +83,7 @@ func (l *tunListener) listenLoop() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
addrs, _ := itf.Addrs()
|
addrs, _ := itf.Addrs()
|
||||||
l.logger.Infof("name: %s, net: %s, mtu: %d, addrs: %s",
|
l.log.Infof("name: %s, net: %s, mtu: %d, addrs: %s",
|
||||||
itf.Name, ip, itf.MTU, addrs)
|
itf.Name, ip, itf.MTU, addrs)
|
||||||
|
|
||||||
var c net.Conn
|
var c net.Conn
|
||||||
@@ -112,7 +112,7 @@ func (l *tunListener) listenLoop() {
|
|||||||
return nil
|
return nil
|
||||||
}()
|
}()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.logger.Error(err)
|
l.log.Error(err)
|
||||||
cancel()
|
cancel()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+43
-35
@@ -7,53 +7,51 @@ import (
|
|||||||
"golang.zx2c4.com/wireguard/tun"
|
"golang.zx2c4.com/wireguard/tun"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
|
||||||
tunOffsetBytes = 16
|
|
||||||
MaxMessageSize = math.MaxUint16
|
|
||||||
)
|
|
||||||
|
|
||||||
type tunDevice struct {
|
type tunDevice struct {
|
||||||
dev tun.Device
|
dev tun.Device
|
||||||
elems [][MaxMessageSize]byte
|
packets int
|
||||||
rbufs [][]byte
|
sizes []int
|
||||||
wbuf [tunOffsetBytes + MaxMessageSize]byte
|
rbufs [][]byte
|
||||||
|
wbufs [][]byte
|
||||||
|
wbuf []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *tunDevice) Read(p []byte) (n int, err error) {
|
func (d *tunDevice) Read(p []byte) (n int, err error) {
|
||||||
if len(d.rbufs) > 0 {
|
if d.packets > 0 {
|
||||||
n = copy(p, d.rbufs[0])
|
for i, size := range d.sizes {
|
||||||
d.rbufs = d.rbufs[1:]
|
if size > 0 {
|
||||||
return
|
n = copy(p, d.rbufs[i][:size])
|
||||||
}
|
|
||||||
|
|
||||||
sizes := make([]int, len(d.elems))
|
d.sizes[i] = 0
|
||||||
bufs := make([][]byte, len(d.elems))
|
d.packets--
|
||||||
for i := range d.elems {
|
return
|
||||||
bufs[i] = d.elems[i][:]
|
}
|
||||||
}
|
|
||||||
|
|
||||||
nn, err := d.dev.Read(bufs, sizes, 0)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := 0; i < nn; i++ {
|
|
||||||
if sizes[i] <= 0 {
|
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
d.rbufs = append(d.rbufs, bufs[i][:sizes[i]])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
n = copy(p, d.rbufs[0])
|
d.rbufs[0] = p
|
||||||
d.rbufs = d.rbufs[1:]
|
packets, err := d.dev.Read(d.rbufs, d.sizes, readOffset)
|
||||||
|
if err != nil && err != tun.ErrTooManySegments {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
n = d.sizes[0]
|
||||||
|
|
||||||
|
d.sizes[0] = 0
|
||||||
|
d.packets = packets - 1
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *tunDevice) Write(p []byte) (n int, err error) {
|
func (d *tunDevice) Write(p []byte) (n int, err error) {
|
||||||
buf := d.wbuf[:]
|
if writeOffset > 0 {
|
||||||
n = copy(buf[tunOffsetBytes:], p)
|
copy(d.wbuf[writeOffset:], p)
|
||||||
_, err = d.dev.Write([][]byte{buf[:tunOffsetBytes+n]}, tunOffsetBytes)
|
d.wbufs[0] = d.wbuf[:writeOffset+len(p)]
|
||||||
|
} else {
|
||||||
|
d.wbufs[0] = p
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = d.dev.Write(d.wbufs, writeOffset)
|
||||||
|
n = len(p)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,9 +65,19 @@ func (l *tunListener) createTunDevice() (dev io.ReadWriteCloser, name string, er
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
batchSize := 16
|
||||||
|
|
||||||
|
rbufs := make([][]byte, batchSize)
|
||||||
|
for i := 1; i < len(rbufs); i++ {
|
||||||
|
rbufs[i] = make([]byte, math.MaxUint16)
|
||||||
|
}
|
||||||
|
|
||||||
dev = &tunDevice{
|
dev = &tunDevice{
|
||||||
dev: ifce,
|
dev: ifce,
|
||||||
elems: make([][MaxMessageSize]byte, ifce.BatchSize()),
|
sizes: make([]int, batchSize),
|
||||||
|
rbufs: rbufs,
|
||||||
|
wbufs: make([][]byte, 1),
|
||||||
|
wbuf: make([]byte, math.MaxUint16+writeOffset),
|
||||||
}
|
}
|
||||||
name, err = ifce.Name()
|
name, err = ifce.Name()
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ import (
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
defaultTunName = "utun"
|
defaultTunName = "utun"
|
||||||
|
readOffset = 4
|
||||||
|
writeOffset = 4
|
||||||
)
|
)
|
||||||
|
|
||||||
func (l *tunListener) createTun() (ifce io.ReadWriteCloser, name string, ip net.IP, err error) {
|
func (l *tunListener) createTun() (ifce io.ReadWriteCloser, name string, ip net.IP, err error) {
|
||||||
|
|||||||
@@ -10,6 +10,11 @@ import (
|
|||||||
"github.com/vishvananda/netlink"
|
"github.com/vishvananda/netlink"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
readOffset = 0
|
||||||
|
writeOffset = 16
|
||||||
|
)
|
||||||
|
|
||||||
func (l *tunListener) createTun() (dev io.ReadWriteCloser, name string, ip net.IP, err error) {
|
func (l *tunListener) createTun() (dev io.ReadWriteCloser, name string, ip net.IP, err error) {
|
||||||
dev, name, err = l.createTunDevice()
|
dev, name, err = l.createTunDevice()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -30,7 +35,7 @@ func (l *tunListener) createTun() (dev io.ReadWriteCloser, name string, ip net.I
|
|||||||
if err = netlink.AddrAdd(link, &netlink.Addr{
|
if err = netlink.AddrAdd(link, &netlink.Addr{
|
||||||
IPNet: &net,
|
IPNet: &net,
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
l.logger.Error(err)
|
l.log.Error(err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -52,7 +57,7 @@ func (l *tunListener) createTun() (dev io.ReadWriteCloser, name string, ip net.I
|
|||||||
}
|
}
|
||||||
if len(dnsServers) > 0 {
|
if len(dnsServers) > 0 {
|
||||||
cmd := fmt.Sprintf("resolvectl dns %s %s", name, strings.Join(dnsServers, " "))
|
cmd := fmt.Sprintf("resolvectl dns %s %s", name, strings.Join(dnsServers, " "))
|
||||||
l.logger.Debug(cmd)
|
l.log.Debug(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 {
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ import (
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
defaultTunName = "tun0"
|
defaultTunName = "tun0"
|
||||||
|
readOffset = 4
|
||||||
|
writeOffset = 4
|
||||||
)
|
)
|
||||||
|
|
||||||
func (l *tunListener) createTun() (ifce io.ReadWriteCloser, name string, ip net.IP, err error) {
|
func (l *tunListener) createTun() (ifce io.ReadWriteCloser, name string, ip net.IP, err error) {
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ import (
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
defaultTunName = "wintun"
|
defaultTunName = "wintun"
|
||||||
|
readOffset = 0
|
||||||
|
writeOffset = 0
|
||||||
)
|
)
|
||||||
|
|
||||||
func (l *tunListener) createTun() (ifce io.ReadWriteCloser, name string, ip net.IP, err error) {
|
func (l *tunListener) createTun() (ifce io.ReadWriteCloser, name string, ip net.IP, err error) {
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
package tun
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"io"
|
||||||
|
"net"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type conn struct {
|
||||||
|
ifce io.ReadWriteCloser
|
||||||
|
laddr net.Addr
|
||||||
|
raddr net.Addr
|
||||||
|
cancel context.CancelFunc
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *conn) Read(b []byte) (n int, err error) {
|
||||||
|
return c.ifce.Read(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *conn) Write(b []byte) (n int, err error) {
|
||||||
|
return c.ifce.Write(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *conn) LocalAddr() net.Addr {
|
||||||
|
return c.laddr
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *conn) RemoteAddr() net.Addr {
|
||||||
|
return c.raddr
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *conn) SetDeadline(t time.Time) error {
|
||||||
|
return &net.OpError{Op: "set", Net: "tun", Source: nil, Addr: nil, Err: errors.New("deadline not supported")}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *conn) SetReadDeadline(t time.Time) error {
|
||||||
|
return &net.OpError{Op: "set", Net: "tun", Source: nil, Addr: nil, Err: errors.New("deadline not supported")}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *conn) SetWriteDeadline(t time.Time) error {
|
||||||
|
return &net.OpError{Op: "set", Net: "tun", Source: nil, Addr: nil, Err: errors.New("deadline not supported")}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *conn) Close() (err error) {
|
||||||
|
if c.cancel != nil {
|
||||||
|
c.cancel()
|
||||||
|
}
|
||||||
|
return c.ifce.Close()
|
||||||
|
}
|
||||||
@@ -0,0 +1,151 @@
|
|||||||
|
package tun
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/go-gost/core/limiter"
|
||||||
|
"github.com/go-gost/core/listener"
|
||||||
|
"github.com/go-gost/core/logger"
|
||||||
|
mdata "github.com/go-gost/core/metadata"
|
||||||
|
"github.com/go-gost/core/router"
|
||||||
|
traffic_limiter "github.com/go-gost/x/limiter/traffic"
|
||||||
|
limiter_wrapper "github.com/go-gost/x/limiter/traffic/wrapper"
|
||||||
|
metrics "github.com/go-gost/x/metrics/wrapper"
|
||||||
|
stats "github.com/go-gost/x/observer/stats/wrapper"
|
||||||
|
"github.com/go-gost/x/registry"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
registry.ListenerRegistry().Register("vtun", NewListener)
|
||||||
|
}
|
||||||
|
|
||||||
|
type tunListener struct {
|
||||||
|
addr net.Addr
|
||||||
|
cqueue chan net.Conn
|
||||||
|
closed chan struct{}
|
||||||
|
log logger.Logger
|
||||||
|
md metadata
|
||||||
|
options listener.Options
|
||||||
|
routes []*router.Route
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewListener(opts ...listener.Option) listener.Listener {
|
||||||
|
options := listener.Options{}
|
||||||
|
for _, opt := range opts {
|
||||||
|
opt(&options)
|
||||||
|
}
|
||||||
|
return &tunListener{
|
||||||
|
log: options.Logger,
|
||||||
|
options: options,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *tunListener) Init(md mdata.Metadata) (err error) {
|
||||||
|
if err = l.parseMetadata(md); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
l.addr = &Addr{Name: l.options.Addr}
|
||||||
|
|
||||||
|
l.cqueue = make(chan net.Conn)
|
||||||
|
l.closed = make(chan struct{})
|
||||||
|
|
||||||
|
go l.listenLoop()
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *tunListener) listenLoop() {
|
||||||
|
for {
|
||||||
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
|
err := func() error {
|
||||||
|
ifce, name, ip, err := l.createTun()
|
||||||
|
if err != nil {
|
||||||
|
if ifce != nil {
|
||||||
|
ifce.Close()
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
itf, err := net.InterfaceByName(name)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
addrs, _ := itf.Addrs()
|
||||||
|
l.log.Infof("name: %s, net: %s, mtu: %d, addrs: %s",
|
||||||
|
itf.Name, ip, itf.MTU, addrs)
|
||||||
|
|
||||||
|
var c net.Conn
|
||||||
|
c = &conn{
|
||||||
|
ifce: ifce,
|
||||||
|
laddr: l.addr,
|
||||||
|
raddr: &net.IPAddr{IP: ip},
|
||||||
|
cancel: cancel,
|
||||||
|
}
|
||||||
|
c = metrics.WrapConn(l.options.Service, c)
|
||||||
|
c = stats.WrapConn(c, l.options.Stats)
|
||||||
|
c = limiter_wrapper.WrapConn(
|
||||||
|
c,
|
||||||
|
l.options.TrafficLimiter,
|
||||||
|
traffic_limiter.ServiceLimitKey,
|
||||||
|
limiter.ScopeOption(limiter.ScopeService),
|
||||||
|
limiter.ServiceOption(l.options.Service),
|
||||||
|
limiter.NetworkOption(c.LocalAddr().Network()),
|
||||||
|
)
|
||||||
|
l.cqueue <- c
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}()
|
||||||
|
if err != nil {
|
||||||
|
l.log.Error(err)
|
||||||
|
cancel()
|
||||||
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
case <-l.closed:
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
time.Sleep(time.Second)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *tunListener) Accept() (net.Conn, error) {
|
||||||
|
select {
|
||||||
|
case conn := <-l.cqueue:
|
||||||
|
return conn, nil
|
||||||
|
case <-l.closed:
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, listener.ErrClosed
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *tunListener) Addr() net.Addr {
|
||||||
|
return l.addr
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *tunListener) Close() error {
|
||||||
|
select {
|
||||||
|
case <-l.closed:
|
||||||
|
return net.ErrClosed
|
||||||
|
default:
|
||||||
|
close(l.closed)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type Addr struct {
|
||||||
|
Name string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Addr) Network() string {
|
||||||
|
return "tun"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Addr) String() string {
|
||||||
|
return a.Name
|
||||||
|
}
|
||||||
@@ -0,0 +1,93 @@
|
|||||||
|
package tun
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
mdata "github.com/go-gost/core/metadata"
|
||||||
|
"github.com/go-gost/core/router"
|
||||||
|
tun_util "github.com/go-gost/x/internal/util/tun"
|
||||||
|
mdutil "github.com/go-gost/x/metadata/util"
|
||||||
|
xrouter "github.com/go-gost/x/router"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
defaultMTU = 1420
|
||||||
|
)
|
||||||
|
|
||||||
|
type metadata struct {
|
||||||
|
config *tun_util.Config
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *tunListener) parseMetadata(md mdata.Metadata) (err error) {
|
||||||
|
config := &tun_util.Config{
|
||||||
|
Name: mdutil.GetString(md, "name", "tun.name"),
|
||||||
|
Peer: mdutil.GetString(md, "peer", "tun.peer"),
|
||||||
|
MTU: mdutil.GetInt(md, "mtu", "tun.mtu"),
|
||||||
|
}
|
||||||
|
if config.MTU <= 0 {
|
||||||
|
config.MTU = defaultMTU
|
||||||
|
}
|
||||||
|
if gw := mdutil.GetString(md, "gw", "tun.gw"); gw != "" {
|
||||||
|
config.Gateway = net.ParseIP(gw)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, s := range strings.Split(mdutil.GetString(md, "net", "tun.net"), ",") {
|
||||||
|
if s = strings.TrimSpace(s); s == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
ip, ipNet, err := net.ParseCIDR(s)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
config.Net = append(config.Net, net.IPNet{
|
||||||
|
IP: ip,
|
||||||
|
Mask: ipNet.Mask,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, s := range strings.Split(mdutil.GetString(md, "route", "tun.route"), ",") {
|
||||||
|
gw := ""
|
||||||
|
if config.Gateway != nil {
|
||||||
|
gw = config.Gateway.String()
|
||||||
|
}
|
||||||
|
if route := xrouter.ParseRoute(strings.TrimSpace(s), gw); route != nil {
|
||||||
|
l.routes = append(l.routes, route)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, s := range mdutil.GetStrings(md, "routes", "tun.routes") {
|
||||||
|
ss := strings.SplitN(s, " ", 2)
|
||||||
|
if len(ss) == 2 {
|
||||||
|
_, ipNet, _ := net.ParseCIDR(strings.TrimSpace(ss[0]))
|
||||||
|
if ipNet == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
gw := net.ParseIP(ss[1])
|
||||||
|
if gw == nil {
|
||||||
|
gw = config.Gateway
|
||||||
|
}
|
||||||
|
|
||||||
|
gateway := ""
|
||||||
|
if gw != nil {
|
||||||
|
gateway = gw.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
l.routes = append(l.routes, &router.Route{
|
||||||
|
Net: ipNet,
|
||||||
|
Dst: ipNet.String(),
|
||||||
|
Gateway: gateway,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, v := range strings.Split(mdutil.GetString(md, "dns", "tun.dns"), ",") {
|
||||||
|
if ip := net.ParseIP(strings.TrimSpace(v)); ip != nil {
|
||||||
|
config.DNS = append(config.DNS, ip)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
l.md.config = config
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
package tun
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"math"
|
||||||
|
|
||||||
|
"github.com/go-gost/core/logger"
|
||||||
|
"golang.zx2c4.com/wireguard/tun"
|
||||||
|
)
|
||||||
|
|
||||||
|
type tunDevice struct {
|
||||||
|
dev tun.Device
|
||||||
|
|
||||||
|
packets int
|
||||||
|
sizes []int
|
||||||
|
rbufs [][]byte
|
||||||
|
wbufs [][]byte
|
||||||
|
wbuf []byte
|
||||||
|
|
||||||
|
log logger.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *tunDevice) Read(p []byte) (n int, err error) {
|
||||||
|
if d.packets > 0 {
|
||||||
|
for i, size := range d.sizes {
|
||||||
|
if size > 0 {
|
||||||
|
n = copy(p, d.rbufs[i][:size])
|
||||||
|
|
||||||
|
d.sizes[i] = 0
|
||||||
|
d.packets--
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
d.rbufs[0] = p
|
||||||
|
packets, err := d.dev.Read(d.rbufs, d.sizes, readOffset)
|
||||||
|
if err != nil && err != tun.ErrTooManySegments {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
n = d.sizes[0]
|
||||||
|
|
||||||
|
d.sizes[0] = 0
|
||||||
|
d.packets = packets - 1
|
||||||
|
|
||||||
|
// d.log.Debugf("read tun: (%d), % x", n, p[:n])
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *tunDevice) Write(p []byte) (n int, err error) {
|
||||||
|
if writeOffset > 0 {
|
||||||
|
copy(d.wbuf[writeOffset:], p)
|
||||||
|
d.wbufs[0] = d.wbuf[:writeOffset+len(p)]
|
||||||
|
} else {
|
||||||
|
d.wbufs[0] = p
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = d.dev.Write(d.wbufs, writeOffset)
|
||||||
|
n = len(p)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *tunDevice) Close() error {
|
||||||
|
return d.dev.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *tunListener) createTunDevice() (dev io.ReadWriteCloser, name string, err error) {
|
||||||
|
ifce, err := tun.CreateTUN(l.md.config.Name, l.md.config.MTU)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
batchSize := 16
|
||||||
|
|
||||||
|
rbufs := make([][]byte, batchSize)
|
||||||
|
for i := 1; i < len(rbufs); i++ {
|
||||||
|
rbufs[i] = make([]byte, math.MaxUint16)
|
||||||
|
}
|
||||||
|
|
||||||
|
dev = &tunDevice{
|
||||||
|
dev: ifce,
|
||||||
|
sizes: make([]int, batchSize),
|
||||||
|
rbufs: rbufs,
|
||||||
|
wbufs: make([][]byte, 1),
|
||||||
|
wbuf: make([]byte, math.MaxUint16+writeOffset),
|
||||||
|
log: l.log,
|
||||||
|
}
|
||||||
|
name, err = ifce.Name()
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
package tun
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net"
|
||||||
|
"os/exec"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
defaultTunName = "utun"
|
||||||
|
readOffset = 4
|
||||||
|
writeOffset = 4
|
||||||
|
)
|
||||||
|
|
||||||
|
func (l *tunListener) createTun() (ifce io.ReadWriteCloser, name string, ip net.IP, err error) {
|
||||||
|
if l.md.config.Name == "" {
|
||||||
|
l.md.config.Name = defaultTunName
|
||||||
|
}
|
||||||
|
ifce, name, err = l.createTunDevice()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
peer := l.md.config.Peer
|
||||||
|
if peer == "" {
|
||||||
|
peer = ip.String()
|
||||||
|
}
|
||||||
|
if len(l.md.config.Net) > 0 {
|
||||||
|
cmd := fmt.Sprintf("ifconfig %s inet %s %s mtu %d up",
|
||||||
|
name, l.md.config.Net[0].String(), l.md.config.Peer, l.md.config.MTU)
|
||||||
|
l.logger.Debug(cmd)
|
||||||
|
args := strings.Split(cmd, " ")
|
||||||
|
if err = exec.Command(args[0], args[1:]...).Run(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ip = l.md.config.Net[0].IP
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = l.addRoutes(name); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *tunListener) addRoutes(ifName string) error {
|
||||||
|
for _, route := range l.routes {
|
||||||
|
cmd := fmt.Sprintf("route add -net %s -interface %s", route.Net.String(), ifName)
|
||||||
|
l.logger.Debug(cmd)
|
||||||
|
args := strings.Split(cmd, " ")
|
||||||
|
if err := exec.Command(args[0], args[1:]...).Run(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,90 @@
|
|||||||
|
package tun
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net"
|
||||||
|
"os/exec"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/vishvananda/netlink"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
readOffset = 0
|
||||||
|
writeOffset = 16
|
||||||
|
)
|
||||||
|
|
||||||
|
func (l *tunListener) createTun() (dev io.ReadWriteCloser, name string, ip net.IP, err error) {
|
||||||
|
dev, name, err = l.createTunDevice()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ifce, err := net.InterfaceByName(name)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
link, err := netlink.LinkByName(name)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, net := range l.md.config.Net {
|
||||||
|
if err = netlink.AddrAdd(link, &netlink.Addr{
|
||||||
|
IPNet: &net,
|
||||||
|
}); err != nil {
|
||||||
|
l.log.Error(err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(l.md.config.Net) > 0 {
|
||||||
|
ip = l.md.config.Net[0].IP
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = netlink.LinkSetUp(link); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = l.addRoutes(ifce); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var dnsServers []string
|
||||||
|
for _, dns := range l.md.config.DNS {
|
||||||
|
dnsServers = append(dnsServers, dns.String())
|
||||||
|
}
|
||||||
|
if len(dnsServers) > 0 {
|
||||||
|
cmd := fmt.Sprintf("resolvectl dns %s %s", name, strings.Join(dnsServers, " "))
|
||||||
|
l.log.Debug(cmd)
|
||||||
|
|
||||||
|
args := strings.Split(cmd, " ")
|
||||||
|
if er := exec.Command(args[0], args[1:]...).Run(); er != nil {
|
||||||
|
err = fmt.Errorf("%s: %v", cmd, er)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *tunListener) addRoutes(ifce *net.Interface) error {
|
||||||
|
for _, route := range l.routes {
|
||||||
|
if route.Net == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
r := netlink.Route{
|
||||||
|
Dst: route.Net,
|
||||||
|
Gw: net.ParseIP(route.Gateway),
|
||||||
|
}
|
||||||
|
if r.Gw == nil {
|
||||||
|
r.LinkIndex = ifce.Index
|
||||||
|
}
|
||||||
|
if err := netlink.RouteReplace(&r); err != nil {
|
||||||
|
return fmt.Errorf("add route %v %v: %v", r.Dst, r.Gw, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
//go:build !linux && !windows && !darwin
|
||||||
|
|
||||||
|
package tun
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net"
|
||||||
|
"os/exec"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
defaultTunName = "tun0"
|
||||||
|
readOffset = 4
|
||||||
|
writeOffset = 4
|
||||||
|
)
|
||||||
|
|
||||||
|
func (l *tunListener) createTun() (ifce io.ReadWriteCloser, name string, ip net.IP, err error) {
|
||||||
|
if l.md.config.Name == "" {
|
||||||
|
l.md.config.Name = defaultTunName
|
||||||
|
}
|
||||||
|
ifce, name, err = l.createTunDevice()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(l.md.config.Net) > 0 {
|
||||||
|
cmd := fmt.Sprintf("ifconfig %s inet %s mtu %d up",
|
||||||
|
name, l.md.config.Net[0].String(), l.md.config.MTU)
|
||||||
|
l.logger.Debug(cmd)
|
||||||
|
|
||||||
|
args := strings.Split(cmd, " ")
|
||||||
|
if er := exec.Command(args[0], args[1:]...).Run(); er != nil {
|
||||||
|
err = fmt.Errorf("%s: %v", cmd, er)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ip = l.md.config.Net[0].IP
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = l.addRoutes(name); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *tunListener) addRoutes(ifName string) error {
|
||||||
|
for _, route := range l.routes {
|
||||||
|
cmd := fmt.Sprintf("route add -net %s -interface %s", route.Net.String(), ifName)
|
||||||
|
l.logger.Debug(cmd)
|
||||||
|
args := strings.Split(cmd, " ")
|
||||||
|
if er := exec.Command(args[0], args[1:]...).Run(); er != nil {
|
||||||
|
return fmt.Errorf("%s: %v", cmd, er)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,87 @@
|
|||||||
|
package tun
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net"
|
||||||
|
"os/exec"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
defaultTunName = "wintun"
|
||||||
|
readOffset = 0
|
||||||
|
writeOffset = 0
|
||||||
|
)
|
||||||
|
|
||||||
|
func (l *tunListener) createTun() (ifce io.ReadWriteCloser, name string, ip net.IP, err error) {
|
||||||
|
if l.md.config.Name == "" {
|
||||||
|
l.md.config.Name = defaultTunName
|
||||||
|
}
|
||||||
|
ifce, name, err = l.createTunDevice()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(l.md.config.Net) > 0 {
|
||||||
|
ipNet := l.md.config.Net[0]
|
||||||
|
cmd := fmt.Sprintf("netsh interface ip set address name=%s "+
|
||||||
|
"source=static addr=%s mask=%s gateway=none",
|
||||||
|
name, ipNet.IP.String(), ipMask(ipNet.Mask))
|
||||||
|
l.logger.Debug(cmd)
|
||||||
|
|
||||||
|
args := strings.Split(cmd, " ")
|
||||||
|
if er := exec.Command(args[0], args[1:]...).Run(); er != nil {
|
||||||
|
err = fmt.Errorf("%s: %v", cmd, er)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ip = ipNet.IP
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = l.addRoutes(name, l.md.config.Gateway); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, dns := range l.md.config.DNS {
|
||||||
|
cmd := fmt.Sprintf("netsh interface ip add dnsservers name=%s address=%s validate=no", name, dns.String())
|
||||||
|
l.logger.Debug(cmd)
|
||||||
|
|
||||||
|
args := strings.Split(cmd, " ")
|
||||||
|
if er := exec.Command(args[0], args[1:]...).Run(); er != nil {
|
||||||
|
err = fmt.Errorf("%s: %v", cmd, er)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *tunListener) addRoutes(ifName string, gw net.IP) error {
|
||||||
|
for _, route := range l.routes {
|
||||||
|
l.deleteRoute(ifName, route.Net.String())
|
||||||
|
|
||||||
|
cmd := fmt.Sprintf("netsh interface ip add route prefix=%s interface=%s store=active",
|
||||||
|
route.Net.String(), ifName)
|
||||||
|
if gw != nil {
|
||||||
|
cmd += " nexthop=" + gw.String()
|
||||||
|
}
|
||||||
|
l.logger.Debug(cmd)
|
||||||
|
args := strings.Split(cmd, " ")
|
||||||
|
if er := exec.Command(args[0], args[1:]...).Run(); er != nil {
|
||||||
|
return fmt.Errorf("%s: %v", cmd, er)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *tunListener) deleteRoute(ifName string, route string) error {
|
||||||
|
cmd := fmt.Sprintf("netsh interface ip delete route prefix=%s interface=%s store=active",
|
||||||
|
route, ifName)
|
||||||
|
l.logger.Debug(cmd)
|
||||||
|
args := strings.Split(cmd, " ")
|
||||||
|
return exec.Command(args[0], args[1:]...).Run()
|
||||||
|
}
|
||||||
|
|
||||||
|
func ipMask(mask net.IPMask) string {
|
||||||
|
return fmt.Sprintf("%d.%d.%d.%d", mask[0], mask[1], mask[2], mask[3])
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user