mirror of
https://github.com/yggdrasil-network/yggdrasil-go.git
synced 2025-08-26 21:17:36 +00:00
Compare commits
9 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
edf179ed26 | ||
![]() |
9950d1225d | ||
![]() |
4fbdeb4e3f | ||
![]() |
5ea16e63a1 | ||
![]() |
da7ebde828 | ||
![]() |
02d92ff81c | ||
![]() |
04c0acf71b | ||
![]() |
8ecc402d7c | ||
![]() |
c505097be0 |
19
CHANGELOG.md
19
CHANGELOG.md
@@ -26,6 +26,25 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
||||
- in case of vulnerabilities.
|
||||
-->
|
||||
|
||||
## [0.5.7] - 2024-08-05
|
||||
|
||||
### Added
|
||||
|
||||
* WebSocket support for peerings, by using the new `ws://` scheme in `Listen` and `Peers`
|
||||
* Additionally, the `wss://` scheme can be used to connect to a WebSocket peer behind a HTTPS reverse proxy
|
||||
|
||||
### Changed
|
||||
|
||||
* On Linux, the TUN adapter now uses vectorised reads/writes where possible, which should reduce the amount of CPU time spent on syscalls and potentially improve throughput
|
||||
* Link error handling has been improved and various link error messages have been rewritten to be clearer
|
||||
* Upgrade dependencies
|
||||
|
||||
### Fixed
|
||||
|
||||
* Multiple multicast connections to the same remote machine should now work correctly
|
||||
* You may get two connections in some cases, one inbound and one outbound, this is known and will not cause problems
|
||||
* Running as a Windows service should be more reliable with service startup and shutdown bugs fixed
|
||||
|
||||
## [0.5.6] - 2024-05-30
|
||||
|
||||
* Go 1.21 is now required to build Yggdrasil
|
||||
|
@@ -53,13 +53,13 @@ func main() {
|
||||
getpkey := flag.Bool("publickey", false, "use in combination with either -useconf or -useconffile, outputs your public key")
|
||||
loglevel := flag.String("loglevel", "info", "loglevel to enable")
|
||||
flag.Parse()
|
||||
|
||||
|
||||
done := make(chan struct{})
|
||||
defer close(done)
|
||||
|
||||
// Catch interrupts from the operating system to exit gracefully.
|
||||
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
|
||||
|
||||
// Capture the service being stopped on Windows.
|
||||
minwinsvc.SetOnExit(cancel)
|
||||
|
||||
// Create a new logger that logs output to stdout.
|
||||
var logger *log.Logger
|
||||
switch *logto {
|
||||
@@ -271,6 +271,14 @@ func main() {
|
||||
n.tun.SetupAdminHandlers(n.admin)
|
||||
}
|
||||
}
|
||||
|
||||
//Windows service shutdown
|
||||
minwinsvc.SetOnExit(func() {
|
||||
logger.Infof("Shutting down service ...")
|
||||
cancel()
|
||||
// Wait for all parts to shutdown properly
|
||||
<-done
|
||||
})
|
||||
|
||||
// Block until we are told to shut down.
|
||||
<-ctx.Done()
|
||||
|
@@ -1,5 +1,5 @@
|
||||
//go:build ios
|
||||
// +build ios
|
||||
//go:build ios || darwin
|
||||
// +build ios darwin
|
||||
|
||||
package mobile
|
||||
|
@@ -1,5 +1,5 @@
|
||||
//go:build !android && !ios
|
||||
// +build !android,!ios
|
||||
//go:build !android && !ios && !darwin
|
||||
// +build !android,!ios,!darwin
|
||||
|
||||
package mobile
|
||||
|
||||
|
25
go.mod
25
go.mod
@@ -5,20 +5,21 @@ go 1.21
|
||||
require (
|
||||
github.com/Arceliar/ironwood v0.0.0-20240529054413-b8e59574e2b2
|
||||
github.com/Arceliar/phony v0.0.0-20220903101357-530938a4b13d
|
||||
github.com/cheggaaa/pb/v3 v3.1.4
|
||||
github.com/cheggaaa/pb/v3 v3.1.5
|
||||
github.com/gologme/log v1.3.0
|
||||
github.com/hashicorp/go-syslog v1.0.0
|
||||
github.com/hjson/hjson-go/v4 v4.4.0
|
||||
github.com/kardianos/minwinsvc v1.0.2
|
||||
github.com/quic-go/quic-go v0.44.0
|
||||
github.com/quic-go/quic-go v0.45.1
|
||||
github.com/vishvananda/netlink v1.1.0
|
||||
golang.org/x/crypto v0.23.0
|
||||
golang.org/x/mobile v0.0.0-20240520174638-fa72addaaa1b
|
||||
golang.org/x/net v0.25.0
|
||||
golang.org/x/sys v0.20.0
|
||||
golang.org/x/text v0.15.0
|
||||
golang.zx2c4.com/wireguard v0.0.0-20230223181233-21636207a675
|
||||
golang.org/x/crypto v0.25.0
|
||||
golang.org/x/mobile v0.0.0-20240716161057-1ad2df20a8b6
|
||||
golang.org/x/net v0.27.0
|
||||
golang.org/x/sys v0.22.0
|
||||
golang.org/x/text v0.16.0
|
||||
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173
|
||||
golang.zx2c4.com/wireguard/windows v0.5.3
|
||||
nhooyr.io/websocket v1.8.11
|
||||
)
|
||||
|
||||
require (
|
||||
@@ -30,10 +31,10 @@ require (
|
||||
github.com/onsi/ginkgo/v2 v2.9.5 // indirect
|
||||
github.com/rivo/uniseg v0.2.0 // indirect
|
||||
go.uber.org/mock v0.4.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 // indirect
|
||||
golang.org/x/mod v0.17.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect
|
||||
golang.org/x/mod v0.19.0 // indirect
|
||||
golang.org/x/sync v0.7.0 // indirect
|
||||
golang.org/x/tools v0.21.0 // indirect
|
||||
golang.org/x/tools v0.23.0 // indirect
|
||||
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
|
||||
)
|
||||
|
||||
@@ -41,7 +42,7 @@ require (
|
||||
github.com/VividCortex/ewma v1.2.0 // indirect
|
||||
github.com/fatih/color v1.15.0 // indirect
|
||||
github.com/mattn/go-isatty v0.0.19 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.14 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.15 // indirect
|
||||
github.com/olekukonko/tablewriter v0.0.5
|
||||
github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f // indirect
|
||||
)
|
||||
|
55
go.sum
55
go.sum
@@ -9,8 +9,8 @@ github.com/bits-and-blooms/bitset v1.13.0 h1:bAQ9OPNFYbGHV6Nez0tmNI0RiEu7/hxlYJR
|
||||
github.com/bits-and-blooms/bitset v1.13.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
|
||||
github.com/bits-and-blooms/bloom/v3 v3.7.0 h1:VfknkqV4xI+PsaDIsoHueyxVDZrfvMn56jeWUzvzdls=
|
||||
github.com/bits-and-blooms/bloom/v3 v3.7.0/go.mod h1:VKlUSvp0lFIYqxJjzdnSsZEw4iHb1kOL2tfHTgyJBHg=
|
||||
github.com/cheggaaa/pb/v3 v3.1.4 h1:DN8j4TVVdKu3WxVwcRKu0sG00IIU6FewoABZzXbRQeo=
|
||||
github.com/cheggaaa/pb/v3 v3.1.4/go.mod h1:6wVjILNBaXMs8c21qRiaUM8BR82erfgau1DQ4iUXmSA=
|
||||
github.com/cheggaaa/pb/v3 v3.1.5 h1:QuuUzeM2WsAqG2gMqtzaWithDJv0i+i6UlnwSCI4QLk=
|
||||
github.com/cheggaaa/pb/v3 v3.1.5/go.mod h1:CrxkeghYTXi1lQBEI7jSn+3svI3cuc19haAj6jM60XI=
|
||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
@@ -27,6 +27,8 @@ github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg
|
||||
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/gologme/log v1.3.0 h1:l781G4dE+pbigClDSDzSaaYKtiueHCILUa/qSDsmHAo=
|
||||
github.com/gologme/log v1.3.0/go.mod h1:yKT+DvIPdDdDoPtqFrFxheooyVmoqi0BAsw+erN3wA4=
|
||||
github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4=
|
||||
github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE=
|
||||
@@ -44,8 +46,8 @@ github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/
|
||||
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
|
||||
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU=
|
||||
github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
|
||||
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
|
||||
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
|
||||
github.com/onsi/ginkgo/v2 v2.9.5 h1:+6Hr4uxzP4XIUyAkg61dWBw8lb/gc4/X5luuxN/EC+Q=
|
||||
@@ -54,8 +56,8 @@ github.com/onsi/gomega v1.27.6 h1:ENqfyGeS5AX/rlXDd/ETokDz93u0YufY1Pgxuy/PvWE=
|
||||
github.com/onsi/gomega v1.27.6/go.mod h1:PIQNjfQwkP3aQAH7lf7j87O/5FiNr+ZR8+ipb+qQlhg=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/quic-go/quic-go v0.44.0 h1:So5wOr7jyO4vzL2sd8/pD9Kesciv91zSk8BoFngItQ0=
|
||||
github.com/quic-go/quic-go v0.44.0/go.mod h1:z4cx/9Ny9UtGITIPzmPTXh1ULfOyWh4qGQlpnPcWmek=
|
||||
github.com/quic-go/quic-go v0.45.1 h1:tPfeYCk+uZHjmDRwHHQmvHRYL2t44ROTujLeFVBmjCA=
|
||||
github.com/quic-go/quic-go v0.45.1/go.mod h1:1dLehS7TIR64+vxGR70GDcatWTOtMX2PUtnKsjbTurI=
|
||||
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
@@ -74,24 +76,25 @@ go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
||||
golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
|
||||
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
|
||||
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 h1:vr/HnozRka3pE4EsMEg1lgkXJkTFJCVUX+S/ZT6wYzM=
|
||||
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc=
|
||||
golang.org/x/mobile v0.0.0-20240520174638-fa72addaaa1b h1:WX7nnnLfCEXg+FmdYZPai2XuP3VqCP1HZVMST0n9DF0=
|
||||
golang.org/x/mobile v0.0.0-20240520174638-fa72addaaa1b/go.mod h1:EiXZlVfUTaAyySFVJb9rsODuiO+WXu8HrUuySb7nYFw=
|
||||
golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30=
|
||||
golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M=
|
||||
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8=
|
||||
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
|
||||
golang.org/x/mobile v0.0.0-20240716161057-1ad2df20a8b6 h1:/VlmIrkuLf2wzPjkZ8imSpckHoW7Y71h66dxbLHSpi8=
|
||||
golang.org/x/mobile v0.0.0-20240716161057-1ad2df20a8b6/go.mod h1:TCsc78+c4cqb8IKEosz2LwJ6YRNkIjMuAYeHYjchGDE=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
|
||||
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/mod v0.19.0 h1:fEdghXQSo20giMthA7cd28ZC+jts4amQ3YMXiP5oMQ8=
|
||||
golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
||||
golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
|
||||
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
||||
golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys=
|
||||
golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE=
|
||||
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.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@@ -110,8 +113,9 @@ 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.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
|
||||
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
|
||||
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
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.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
@@ -124,26 +128,31 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
|
||||
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
|
||||
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
|
||||
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
|
||||
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.21.0 h1:qc0xYgIbsSDt9EyWz05J5wfa7LOVW0YTLOXrqdLAWIw=
|
||||
golang.org/x/tools v0.21.0/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
|
||||
golang.org/x/tools v0.23.0 h1:SGsXPZ+2l4JsgaCKkx+FQ9YZ5XEtA1GZYuoDjenLjvg=
|
||||
golang.org/x/tools v0.23.0/go.mod h1:pnu6ufv6vQkll6szChhK3C3L/ruaIv5eBeztNG8wtsI=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/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/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI=
|
||||
golang.zx2c4.com/wireguard v0.0.0-20230223181233-21636207a675 h1:/J/RVnr7ng4fWPRH3xa4WtBJ1Jp+Auu4YNLmGiPv5QU=
|
||||
golang.zx2c4.com/wireguard v0.0.0-20230223181233-21636207a675/go.mod h1:whfbyDBt09xhCYQWtO2+3UVjlaq6/9hDZrjg2ZE6SyA=
|
||||
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173 h1:/jFs0duh4rdb8uIfPMv78iAJGcPKDeqAFnaLBropIC4=
|
||||
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173/go.mod h1:tkCQ4FQXmpAgYVh++1cq16/dH4QJtmvpRv19DWGAHSA=
|
||||
golang.zx2c4.com/wireguard/windows v0.5.3 h1:On6j2Rpn3OEMXqBq00QEDC7bWSZrPIHKIus8eIuExIE=
|
||||
golang.zx2c4.com/wireguard/windows v0.5.3/go.mod h1:9TEe8TJmtwyQebdFwAkEWOPr3prrtqm+REGFifP60hI=
|
||||
google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw=
|
||||
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
|
||||
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
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/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gvisor.dev/gvisor v0.0.0-20230927004350-cbd86285d259 h1:TbRPT0HtzFP3Cno1zZo7yPzEEnfu8EjLfl6IU9VfqkQ=
|
||||
gvisor.dev/gvisor v0.0.0-20230927004350-cbd86285d259/go.mod h1:AVgIgHMwK63XvmAzWG9vLQ41YnVHN0du0tEC46fI7yY=
|
||||
nhooyr.io/websocket v1.8.11 h1:f/qXNc2/3DpoSZkHt1DQu6rj4zGC8JmkkLkWss0MgN0=
|
||||
nhooyr.io/websocket v1.8.11/go.mod h1:rN9OFWIUwuxg4fR5tELlYC04bXYowCP9GX47ivo2l+c=
|
||||
|
@@ -12,7 +12,7 @@ type AddPeerRequest struct {
|
||||
|
||||
type AddPeerResponse struct{}
|
||||
|
||||
func (a *AdminSocket) addPeerHandler(req *AddPeerRequest, res *AddPeerResponse) error {
|
||||
func (a *AdminSocket) addPeerHandler(req *AddPeerRequest, _ *AddPeerResponse) error {
|
||||
u, err := url.Parse(req.Uri)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to parse peering URI: %w", err)
|
||||
|
@@ -201,10 +201,6 @@ func (a *AdminSocket) SetupAdminHandlers() {
|
||||
return res, nil
|
||||
},
|
||||
)
|
||||
//_ = a.AddHandler("getNodeInfo", []string{"key"}, t.proto.nodeinfo.nodeInfoAdminHandler)
|
||||
//_ = a.AddHandler("debug_remoteGetSelf", []string{"key"}, t.proto.getSelfHandler)
|
||||
//_ = a.AddHandler("debug_remoteGetPeers", []string{"key"}, t.proto.getPeersHandler)
|
||||
//_ = a.AddHandler("debug_remoteGetDHT", []string{"key"}, t.proto.getDHTHandler)
|
||||
}
|
||||
|
||||
// IsStarted returns true if the module has been started.
|
||||
@@ -269,7 +265,6 @@ func (a *AdminSocket) listen() {
|
||||
case "tcp":
|
||||
a.listener, err = net.Listen("tcp", u.Host)
|
||||
default:
|
||||
// err = errors.New(fmt.Sprint("protocol not supported: ", u.Scheme))
|
||||
a.listener, err = net.Listen("tcp", listenaddr)
|
||||
}
|
||||
} else {
|
||||
@@ -309,23 +304,6 @@ func (a *AdminSocket) handleRequest(conn net.Conn) {
|
||||
|
||||
defer conn.Close()
|
||||
|
||||
/*
|
||||
defer func() {
|
||||
r := recover()
|
||||
if r != nil {
|
||||
fmt.Println("ERROR:", r)
|
||||
a.log.Debugln("Admin socket error:", r)
|
||||
if err := encoder.Encode(&ErrorResponse{
|
||||
Error: "Check your syntax and input types",
|
||||
}); err != nil {
|
||||
fmt.Println("ERROR 2:", err)
|
||||
a.log.Debugln("Admin socket JSON encode error:", err)
|
||||
}
|
||||
conn.Close()
|
||||
}
|
||||
}()
|
||||
*/
|
||||
|
||||
for {
|
||||
var err error
|
||||
var buf json.RawMessage
|
||||
|
@@ -23,7 +23,7 @@ type PathEntry struct {
|
||||
Sequence uint64 `json:"sequence"`
|
||||
}
|
||||
|
||||
func (a *AdminSocket) getPathsHandler(req *GetPathsRequest, res *GetPathsResponse) error {
|
||||
func (a *AdminSocket) getPathsHandler(_ *GetPathsRequest, res *GetPathsResponse) error {
|
||||
paths := a.core.GetPaths()
|
||||
res.Paths = make([]PathEntry, 0, len(paths))
|
||||
for _, p := range paths {
|
||||
|
@@ -32,7 +32,7 @@ type PeerEntry struct {
|
||||
LastError string `json:"last_error,omitempty"`
|
||||
}
|
||||
|
||||
func (a *AdminSocket) getPeersHandler(req *GetPeersRequest, res *GetPeersResponse) error {
|
||||
func (a *AdminSocket) getPeersHandler(_ *GetPeersRequest, res *GetPeersResponse) error {
|
||||
peers := a.core.GetPeers()
|
||||
res.Peers = make([]PeerEntry, 0, len(peers))
|
||||
for _, p := range peers {
|
||||
|
@@ -17,7 +17,7 @@ type GetSelfResponse struct {
|
||||
Subnet string `json:"subnet"`
|
||||
}
|
||||
|
||||
func (a *AdminSocket) getSelfHandler(req *GetSelfRequest, res *GetSelfResponse) error {
|
||||
func (a *AdminSocket) getSelfHandler(_ *GetSelfRequest, res *GetSelfResponse) error {
|
||||
self := a.core.GetSelf()
|
||||
snet := a.core.Subnet()
|
||||
res.BuildName = version.BuildName()
|
||||
|
@@ -23,7 +23,7 @@ type SessionEntry struct {
|
||||
Uptime float64 `json:"uptime"`
|
||||
}
|
||||
|
||||
func (a *AdminSocket) getSessionsHandler(req *GetSessionsRequest, res *GetSessionsResponse) error {
|
||||
func (a *AdminSocket) getSessionsHandler(_ *GetSessionsRequest, res *GetSessionsResponse) error {
|
||||
sessions := a.core.GetSessions()
|
||||
res.Sessions = make([]SessionEntry, 0, len(sessions))
|
||||
for _, s := range sessions {
|
||||
|
@@ -20,11 +20,9 @@ type TreeEntry struct {
|
||||
PublicKey string `json:"key"`
|
||||
Parent string `json:"parent"`
|
||||
Sequence uint64 `json:"sequence"`
|
||||
//Port uint64 `json:"port"`
|
||||
//Rest uint64 `json:"rest"`
|
||||
}
|
||||
|
||||
func (a *AdminSocket) getTreeHandler(req *GetTreeRequest, res *GetTreeResponse) error {
|
||||
func (a *AdminSocket) getTreeHandler(_ *GetTreeRequest, res *GetTreeResponse) error {
|
||||
tree := a.core.GetTree()
|
||||
res.Tree = make([]TreeEntry, 0, len(tree))
|
||||
for _, d := range tree {
|
||||
@@ -34,8 +32,6 @@ func (a *AdminSocket) getTreeHandler(req *GetTreeRequest, res *GetTreeResponse)
|
||||
PublicKey: hex.EncodeToString(d.Key[:]),
|
||||
Parent: hex.EncodeToString(d.Parent[:]),
|
||||
Sequence: d.Sequence,
|
||||
//Port: d.Port,
|
||||
//Rest: d.Rest,
|
||||
})
|
||||
}
|
||||
sort.SliceStable(res.Tree, func(i, j int) bool {
|
||||
|
@@ -12,7 +12,7 @@ type RemovePeerRequest struct {
|
||||
|
||||
type RemovePeerResponse struct{}
|
||||
|
||||
func (a *AdminSocket) removePeerHandler(req *RemovePeerRequest, res *RemovePeerResponse) error {
|
||||
func (a *AdminSocket) removePeerHandler(req *RemovePeerRequest, _ *RemovePeerResponse) error {
|
||||
u, err := url.Parse(req.Uri)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to parse peering URI: %w", err)
|
||||
|
@@ -7,7 +7,6 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"net/netip"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -38,6 +37,8 @@ type links struct {
|
||||
unix *linkUNIX // UNIX interface support
|
||||
socks *linkSOCKS // SOCKS interface support
|
||||
quic *linkQUIC // QUIC interface support
|
||||
ws *linkWS // WS interface support
|
||||
wss *linkWSS // WSS interface support
|
||||
// _links can only be modified safely from within the links actor
|
||||
_links map[linkInfo]*link // *link is nil if connection in progress
|
||||
}
|
||||
@@ -98,6 +99,8 @@ func (l *links) init(c *Core) error {
|
||||
l.unix = l.newLinkUNIX()
|
||||
l.socks = l.newLinkSOCKS()
|
||||
l.quic = l.newLinkQUIC()
|
||||
l.ws = l.newLinkWS()
|
||||
l.wss = l.newLinkWSS()
|
||||
l._links = make(map[linkInfo]*link)
|
||||
|
||||
var listeners []ListenAddress
|
||||
@@ -137,7 +140,7 @@ const ErrLinkAlreadyConfigured = linkError("peer is already configured")
|
||||
const ErrLinkNotConfigured = linkError("peer is not configured")
|
||||
const ErrLinkPriorityInvalid = linkError("priority value is invalid")
|
||||
const ErrLinkPinnedKeyInvalid = linkError("pinned public key is invalid")
|
||||
const ErrLinkPasswordInvalid = linkError("password is invalid")
|
||||
const ErrLinkPasswordInvalid = linkError("invalid password supplied")
|
||||
const ErrLinkUnrecognisedSchema = linkError("link schema unknown")
|
||||
const ErrLinkMaxBackoffInvalid = linkError("max backoff duration invalid")
|
||||
|
||||
@@ -360,9 +363,11 @@ func (l *links) add(u *url.URL, sintf string, linkType linkType) error {
|
||||
_ = lc.Close()
|
||||
phony.Block(l, func() {
|
||||
state._conn = nil
|
||||
if state._err = err; state._err != nil {
|
||||
state._errtime = time.Now()
|
||||
if err == nil {
|
||||
err = fmt.Errorf("remote side closed the connection")
|
||||
}
|
||||
state._err = err
|
||||
state._errtime = time.Now()
|
||||
})
|
||||
|
||||
// If the link is persistently configured, back off if needed
|
||||
@@ -379,7 +384,7 @@ func (l *links) add(u *url.URL, sintf string, linkType linkType) error {
|
||||
return retErr
|
||||
}
|
||||
|
||||
func (l *links) remove(u *url.URL, sintf string, linkType linkType) error {
|
||||
func (l *links) remove(u *url.URL, sintf string, _ linkType) error {
|
||||
var retErr error
|
||||
phony.Block(l, func() {
|
||||
// Generate the link info and see whether we think we already
|
||||
@@ -418,6 +423,10 @@ func (l *links) listen(u *url.URL, sintf string) (*Listener, error) {
|
||||
protocol = l.unix
|
||||
case "quic":
|
||||
protocol = l.quic
|
||||
case "ws":
|
||||
protocol = l.ws
|
||||
case "wss":
|
||||
protocol = l.wss
|
||||
default:
|
||||
cancel()
|
||||
return nil, ErrLinkUnrecognisedSchema
|
||||
@@ -546,6 +555,10 @@ func (l *links) connect(ctx context.Context, u *url.URL, info linkInfo, options
|
||||
dialer = l.unix
|
||||
case "quic":
|
||||
dialer = l.quic
|
||||
case "ws":
|
||||
dialer = l.ws
|
||||
case "wss":
|
||||
dialer = l.wss
|
||||
default:
|
||||
return nil, ErrLinkUnrecognisedSchema
|
||||
}
|
||||
@@ -567,7 +580,7 @@ func (l *links) handler(linkType linkType, options linkOptions, conn net.Conn, s
|
||||
switch {
|
||||
case err != nil:
|
||||
return fmt.Errorf("write handshake: %w", err)
|
||||
case err == nil && n != len(metaBytes):
|
||||
case n != len(metaBytes):
|
||||
return fmt.Errorf("incomplete handshake send")
|
||||
}
|
||||
meta = version_metadata{}
|
||||
@@ -636,21 +649,11 @@ func (l *links) handler(linkType linkType, options linkOptions, conn net.Conn, s
|
||||
l.core.log.Infof("Disconnected %s: %s, source %s; error: %s",
|
||||
dir, remoteStr, localStr, err)
|
||||
}
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
|
||||
func urlForLinkInfo(u url.URL) url.URL {
|
||||
u.RawQuery = ""
|
||||
if host, _, err := net.SplitHostPort(u.Host); err == nil {
|
||||
if addr, err := netip.ParseAddr(host); err == nil {
|
||||
// For peers that look like multicast peers (i.e.
|
||||
// link-local addresses), we will ignore the port number,
|
||||
// otherwise we might open multiple connections to them.
|
||||
if addr.IsLinkLocalUnicast() {
|
||||
u.Host = fmt.Sprintf("[%s]", addr.String())
|
||||
}
|
||||
}
|
||||
}
|
||||
return u
|
||||
}
|
||||
|
||||
|
@@ -28,6 +28,6 @@ func (t *linkTCP) tcpContext(network, address string, c syscall.RawConn) error {
|
||||
}
|
||||
}
|
||||
|
||||
func (t *linkTCP) getControl(sintf string) func(string, string, syscall.RawConn) error {
|
||||
func (t *linkTCP) getControl(_ string) func(string, string, syscall.RawConn) error {
|
||||
return t.tcpContext
|
||||
}
|
||||
|
123
src/core/link_ws.go
Normal file
123
src/core/link_ws.go
Normal file
@@ -0,0 +1,123 @@
|
||||
package core
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
"github.com/Arceliar/phony"
|
||||
"nhooyr.io/websocket"
|
||||
)
|
||||
|
||||
type linkWS struct {
|
||||
phony.Inbox
|
||||
*links
|
||||
}
|
||||
|
||||
type linkWSConn struct {
|
||||
net.Conn
|
||||
}
|
||||
|
||||
type linkWSListener struct {
|
||||
ch chan *linkWSConn
|
||||
ctx context.Context
|
||||
httpServer *http.Server
|
||||
listener net.Listener
|
||||
}
|
||||
|
||||
type wsServer struct {
|
||||
ch chan *linkWSConn
|
||||
ctx context.Context
|
||||
}
|
||||
|
||||
func (l *linkWSListener) Accept() (net.Conn, error) {
|
||||
qs := <-l.ch
|
||||
if qs == nil {
|
||||
return nil, context.Canceled
|
||||
}
|
||||
return qs, nil
|
||||
}
|
||||
|
||||
func (l *linkWSListener) Addr() net.Addr {
|
||||
return l.listener.Addr()
|
||||
}
|
||||
|
||||
func (l *linkWSListener) Close() error {
|
||||
if err := l.httpServer.Shutdown(l.ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
return l.listener.Close()
|
||||
}
|
||||
|
||||
func (s *wsServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
if r.URL.Path == "/health" || r.URL.Path == "/healthz" {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
_, _ = w.Write([]byte("OK"))
|
||||
return
|
||||
}
|
||||
|
||||
c, err := websocket.Accept(w, r, &websocket.AcceptOptions{
|
||||
Subprotocols: []string{"ygg-ws"},
|
||||
})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if c.Subprotocol() != "ygg-ws" {
|
||||
c.Close(websocket.StatusPolicyViolation, "client must speak the ygg-ws subprotocol")
|
||||
return
|
||||
}
|
||||
|
||||
s.ch <- &linkWSConn{
|
||||
Conn: websocket.NetConn(s.ctx, c, websocket.MessageBinary),
|
||||
}
|
||||
}
|
||||
|
||||
func (l *links) newLinkWS() *linkWS {
|
||||
lt := &linkWS{
|
||||
links: l,
|
||||
}
|
||||
return lt
|
||||
}
|
||||
|
||||
func (l *linkWS) dial(ctx context.Context, url *url.URL, info linkInfo, options linkOptions) (net.Conn, error) {
|
||||
wsconn, _, err := websocket.Dial(ctx, url.String(), &websocket.DialOptions{
|
||||
Subprotocols: []string{"ygg-ws"},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &linkWSConn{
|
||||
Conn: websocket.NetConn(ctx, wsconn, websocket.MessageBinary),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (l *linkWS) listen(ctx context.Context, url *url.URL, _ string) (net.Listener, error) {
|
||||
nl, err := net.Listen("tcp", url.Host)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ch := make(chan *linkWSConn)
|
||||
|
||||
httpServer := &http.Server{
|
||||
Handler: &wsServer{
|
||||
ch: ch,
|
||||
ctx: ctx,
|
||||
},
|
||||
BaseContext: func(_ net.Listener) context.Context { return ctx },
|
||||
ReadTimeout: time.Second * 10,
|
||||
WriteTimeout: time.Second * 10,
|
||||
}
|
||||
|
||||
lwl := &linkWSListener{
|
||||
ch: ch,
|
||||
ctx: ctx,
|
||||
httpServer: httpServer,
|
||||
listener: nl,
|
||||
}
|
||||
go lwl.httpServer.Serve(nl) // nolint:errcheck
|
||||
return lwl, nil
|
||||
}
|
43
src/core/link_wss.go
Normal file
43
src/core/link_wss.go
Normal file
@@ -0,0 +1,43 @@
|
||||
package core
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/url"
|
||||
|
||||
"github.com/Arceliar/phony"
|
||||
"nhooyr.io/websocket"
|
||||
)
|
||||
|
||||
type linkWSS struct {
|
||||
phony.Inbox
|
||||
*links
|
||||
}
|
||||
|
||||
type linkWSSConn struct {
|
||||
net.Conn
|
||||
}
|
||||
|
||||
func (l *links) newLinkWSS() *linkWSS {
|
||||
lwss := &linkWSS{
|
||||
links: l,
|
||||
}
|
||||
return lwss
|
||||
}
|
||||
|
||||
func (l *linkWSS) dial(ctx context.Context, url *url.URL, info linkInfo, options linkOptions) (net.Conn, error) {
|
||||
wsconn, _, err := websocket.Dial(ctx, url.String(), &websocket.DialOptions{
|
||||
Subprotocols: []string{"ygg-ws"},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &linkWSSConn{
|
||||
Conn: websocket.NetConn(ctx, wsconn, websocket.MessageBinary),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (l *linkWSS) listen(ctx context.Context, url *url.URL, _ string) (net.Listener, error) {
|
||||
return nil, fmt.Errorf("WSS listener not supported, use WS listener behind reverse proxy instead")
|
||||
}
|
@@ -8,7 +8,6 @@ import (
|
||||
"bytes"
|
||||
"crypto/ed25519"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"golang.org/x/crypto/blake2b"
|
||||
@@ -38,6 +37,16 @@ const (
|
||||
metaPriority // uint8
|
||||
)
|
||||
|
||||
type handshakeError string
|
||||
|
||||
func (e handshakeError) Error() string { return string(e) }
|
||||
|
||||
const ErrHandshakeInvalidPreamble = handshakeError("invalid handshake, remote side is not Yggdrasil")
|
||||
const ErrHandshakeInvalidLength = handshakeError("invalid handshake length, possible version mismatch")
|
||||
const ErrHandshakeInvalidPassword = handshakeError("invalid password supplied, check your config")
|
||||
const ErrHandshakeHashFailure = handshakeError("invalid hash length")
|
||||
const ErrHandshakeIncorrectPassword = handshakeError("password does not match remote side")
|
||||
|
||||
// Gets a base metadata with no keys set, but with the correct version numbers.
|
||||
func version_getBaseMetadata() version_metadata {
|
||||
return version_metadata{
|
||||
@@ -77,7 +86,7 @@ func (m *version_metadata) encode(privateKey ed25519.PrivateKey, password []byte
|
||||
return nil, err
|
||||
}
|
||||
if n != ed25519.PublicKeySize {
|
||||
return nil, fmt.Errorf("hash writer only wrote %d bytes", n)
|
||||
return nil, ErrHandshakeHashFailure
|
||||
}
|
||||
hash := hasher.Sum(nil)
|
||||
bs = append(bs, ed25519.Sign(privateKey, hash)...)
|
||||
@@ -94,11 +103,11 @@ func (m *version_metadata) decode(r io.Reader, password []byte) error {
|
||||
}
|
||||
meta := [4]byte{'m', 'e', 't', 'a'}
|
||||
if !bytes.Equal(bh[:4], meta[:]) {
|
||||
return fmt.Errorf("invalid handshake preamble")
|
||||
return ErrHandshakeInvalidPreamble
|
||||
}
|
||||
hl := binary.BigEndian.Uint16(bh[4:6])
|
||||
if hl < ed25519.SignatureSize {
|
||||
return fmt.Errorf("invalid handshake length")
|
||||
return ErrHandshakeInvalidLength
|
||||
}
|
||||
bs := make([]byte, hl)
|
||||
if _, err := io.ReadFull(r, bs); err != nil {
|
||||
@@ -132,15 +141,15 @@ func (m *version_metadata) decode(r io.Reader, password []byte) error {
|
||||
|
||||
hasher, err := blake2b.New512(password)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid password supplied")
|
||||
return ErrHandshakeInvalidPassword
|
||||
}
|
||||
n, err := hasher.Write(m.publicKey)
|
||||
if err != nil || n != ed25519.PublicKeySize {
|
||||
return fmt.Errorf("failed to generate hash")
|
||||
return ErrHandshakeHashFailure
|
||||
}
|
||||
hash := hasher.Sum(nil)
|
||||
if !ed25519.Verify(m.publicKey, hash, sig) {
|
||||
return fmt.Errorf("password is incorrect")
|
||||
return ErrHandshakeIncorrectPassword
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@@ -11,7 +11,7 @@ type GetMulticastInterfacesResponse struct {
|
||||
Interfaces []string `json:"multicast_interfaces"`
|
||||
}
|
||||
|
||||
func (m *Multicast) getMulticastInterfacesHandler(req *GetMulticastInterfacesRequest, res *GetMulticastInterfacesResponse) error {
|
||||
func (m *Multicast) getMulticastInterfacesHandler(_ *GetMulticastInterfacesRequest, res *GetMulticastInterfacesResponse) error {
|
||||
res.Interfaces = []string{}
|
||||
for _, v := range m.Interfaces() {
|
||||
res.Interfaces = append(res.Interfaces, v.Name)
|
||||
|
@@ -1,42 +1,60 @@
|
||||
package tun
|
||||
|
||||
const TUN_OFFSET_BYTES = 4
|
||||
const TUN_OFFSET_BYTES = 80 // sizeof(virtio_net_hdr)
|
||||
|
||||
func (tun *TunAdapter) read() {
|
||||
var buf [TUN_OFFSET_BYTES + 65535]byte
|
||||
vs := tun.iface.BatchSize()
|
||||
bufs := make([][]byte, vs)
|
||||
sizes := make([]int, vs)
|
||||
for i := range bufs {
|
||||
bufs[i] = make([]byte, TUN_OFFSET_BYTES+65535)
|
||||
}
|
||||
for {
|
||||
n, err := tun.iface.Read(buf[:], TUN_OFFSET_BYTES)
|
||||
if n <= TUN_OFFSET_BYTES || err != nil {
|
||||
n, err := tun.iface.Read(bufs, sizes, TUN_OFFSET_BYTES)
|
||||
if err != nil {
|
||||
tun.log.Errorln("Error reading TUN:", err)
|
||||
ferr := tun.iface.Flush()
|
||||
if ferr != nil {
|
||||
tun.log.Errorln("Unable to flush packets:", ferr)
|
||||
}
|
||||
return
|
||||
}
|
||||
begin := TUN_OFFSET_BYTES
|
||||
end := begin + n
|
||||
bs := buf[begin:end]
|
||||
if _, err := tun.rwc.Write(bs); err != nil {
|
||||
tun.log.Debugln("Unable to send packet:", err)
|
||||
for i, b := range bufs[:n] {
|
||||
if _, err := tun.rwc.Write(b[TUN_OFFSET_BYTES : TUN_OFFSET_BYTES+sizes[i]]); err != nil {
|
||||
tun.log.Debugln("Unable to send packet:", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (tun *TunAdapter) write() {
|
||||
var buf [TUN_OFFSET_BYTES + 65535]byte
|
||||
func (tun *TunAdapter) queue() {
|
||||
for {
|
||||
bs := buf[TUN_OFFSET_BYTES:]
|
||||
n, err := tun.rwc.Read(bs)
|
||||
p := bufPool.Get().([]byte)[:bufPoolSize]
|
||||
n, err := tun.rwc.Read(p)
|
||||
if err != nil {
|
||||
tun.log.Errorln("Exiting TUN writer due to core read error:", err)
|
||||
return
|
||||
}
|
||||
tun.ch <- p[:n]
|
||||
}
|
||||
}
|
||||
|
||||
func (tun *TunAdapter) write() {
|
||||
vs := cap(tun.ch)
|
||||
bufs := make([][]byte, vs)
|
||||
for i := range bufs {
|
||||
bufs[i] = make([]byte, TUN_OFFSET_BYTES+65535)
|
||||
}
|
||||
for {
|
||||
n := len(tun.ch)
|
||||
if n == 0 {
|
||||
n = 1 // Nothing queued up yet, wait for it instead
|
||||
}
|
||||
for i := 0; i < n; i++ {
|
||||
msg := <-tun.ch
|
||||
bufs[i] = append(bufs[i][:TUN_OFFSET_BYTES], msg...)
|
||||
bufPool.Put(msg) // nolint:staticcheck
|
||||
}
|
||||
if !tun.isEnabled {
|
||||
continue // Nothing to do, the tun isn't enabled
|
||||
}
|
||||
bs = buf[:TUN_OFFSET_BYTES+n]
|
||||
if _, err = tun.iface.Write(bs, TUN_OFFSET_BYTES); err != nil {
|
||||
if _, err := tun.iface.Write(bufs[:n], TUN_OFFSET_BYTES); err != nil {
|
||||
tun.Act(nil, func() {
|
||||
if !tun.isOpen {
|
||||
tun.log.Errorln("TUN iface write error:", err)
|
||||
|
@@ -10,9 +10,11 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/Arceliar/phony"
|
||||
"golang.zx2c4.com/wireguard/tun"
|
||||
wgtun "golang.zx2c4.com/wireguard/tun"
|
||||
|
||||
"github.com/yggdrasil-network/yggdrasil-go/src/address"
|
||||
"github.com/yggdrasil-network/yggdrasil-go/src/config"
|
||||
@@ -39,7 +41,7 @@ type TunAdapter struct {
|
||||
addr address.Address
|
||||
subnet address.Subnet
|
||||
mtu uint64
|
||||
iface tun.Device
|
||||
iface wgtun.Device
|
||||
phony.Inbox // Currently only used for _handlePacket from the reader, TODO: all the stuff that currently needs a mutex below
|
||||
isOpen bool
|
||||
isEnabled bool // Used by the writer to drop sessionTraffic if not enabled
|
||||
@@ -48,6 +50,7 @@ type TunAdapter struct {
|
||||
name InterfaceName
|
||||
mtu InterfaceMTU
|
||||
}
|
||||
ch chan []byte
|
||||
}
|
||||
|
||||
// Gets the maximum supported MTU for the platform based on the defaults in
|
||||
@@ -62,6 +65,20 @@ func getSupportedMTU(mtu uint64) uint64 {
|
||||
return mtu
|
||||
}
|
||||
|
||||
func waitForTUNUp(ch <-chan wgtun.Event) bool {
|
||||
t := time.After(time.Second * 5)
|
||||
for {
|
||||
select {
|
||||
case ev := <-ch:
|
||||
if ev == wgtun.EventUp {
|
||||
return true
|
||||
}
|
||||
case <-t:
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Name returns the name of the adapter, e.g. "tun0". On Windows, this may
|
||||
// return a canonical adapter name instead.
|
||||
func (tun *TunAdapter) Name() string {
|
||||
@@ -145,6 +162,8 @@ func (tun *TunAdapter) _start() error {
|
||||
tun.rwc.SetMTU(tun.MTU())
|
||||
tun.isOpen = true
|
||||
tun.isEnabled = true
|
||||
tun.ch = make(chan []byte, tun.iface.BatchSize())
|
||||
go tun.queue()
|
||||
go tun.read()
|
||||
go tun.write()
|
||||
return nil
|
||||
@@ -178,3 +197,12 @@ func (tun *TunAdapter) _stop() error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
const bufPoolSize = TUN_OFFSET_BYTES + 65535
|
||||
|
||||
var bufPool = sync.Pool{
|
||||
New: func() any {
|
||||
b := [bufPoolSize]byte{}
|
||||
return b[:]
|
||||
},
|
||||
}
|
||||
|
@@ -80,6 +80,9 @@ func (tun *TunAdapter) setup(ifname string, addr string, mtu uint64) error {
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create TUN: %w", err)
|
||||
}
|
||||
if !waitForTUNUp(iface.Events()) {
|
||||
return fmt.Errorf("TUN did not come up in time")
|
||||
}
|
||||
tun.iface = iface
|
||||
if mtu, err := iface.MTU(); err == nil {
|
||||
tun.mtu = getSupportedMTU(uint64(mtu))
|
||||
|
@@ -27,6 +27,9 @@ func (tun *TunAdapter) setup(ifname string, addr string, mtu uint64) error {
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create TUN: %w", err)
|
||||
}
|
||||
if !waitForTUNUp(iface.Events()) {
|
||||
return fmt.Errorf("TUN did not come up in time")
|
||||
}
|
||||
tun.iface = iface
|
||||
if m, err := iface.MTU(); err == nil {
|
||||
tun.mtu = getSupportedMTU(uint64(m))
|
||||
@@ -55,6 +58,9 @@ func (tun *TunAdapter) setupFD(fd int32, addr string, mtu uint64) error {
|
||||
unix.Close(dfd)
|
||||
return fmt.Errorf("failed to create TUN from FD: %w", err)
|
||||
}
|
||||
if !waitForTUNUp(iface.Events()) {
|
||||
return fmt.Errorf("TUN did not come up in time")
|
||||
}
|
||||
tun.iface = iface
|
||||
if m, err := iface.MTU(); err == nil {
|
||||
tun.mtu = getSupportedMTU(uint64(m))
|
||||
|
@@ -21,6 +21,9 @@ func (tun *TunAdapter) setup(ifname string, addr string, mtu uint64) error {
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create TUN: %w", err)
|
||||
}
|
||||
if !waitForTUNUp(iface.Events()) {
|
||||
return fmt.Errorf("TUN did not come up in time")
|
||||
}
|
||||
tun.iface = iface
|
||||
if mtu, err := iface.MTU(); err == nil {
|
||||
tun.mtu = getSupportedMTU(uint64(mtu))
|
||||
|
@@ -18,6 +18,9 @@ func (tun *TunAdapter) setup(ifname string, addr string, mtu uint64) error {
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create TUN: %w", err)
|
||||
}
|
||||
if !waitForTUNUp(iface.Events()) {
|
||||
return fmt.Errorf("TUN did not come up in time")
|
||||
}
|
||||
tun.iface = iface
|
||||
if mtu, err := iface.MTU(); err == nil {
|
||||
tun.mtu = getSupportedMTU(uint64(mtu))
|
||||
|
@@ -34,6 +34,9 @@ func (tun *TunAdapter) setup(ifname string, addr string, mtu uint64) error {
|
||||
if iface, err = wgtun.CreateTUNWithRequestedGUID(ifname, &guid, int(mtu)); err != nil {
|
||||
return err
|
||||
}
|
||||
if !waitForTUNUp(iface.Events()) {
|
||||
return fmt.Errorf("TUN did not come up in time")
|
||||
}
|
||||
tun.iface = iface
|
||||
if addr != "" {
|
||||
if err = tun.setupAddress(addr); err != nil {
|
||||
|
Reference in New Issue
Block a user