mirror of
https://github.com/tailscale/tailscale.git
synced 2024-11-29 04:55:31 +00:00
net/dns, paths, util/winutil: change net/dns/windowsManager NRPT management to support more than 50 domains.
AFAICT this isn't documented on MSDN, but based on the issue referenced below, NRPT rules are not working when a rule specifies > 50 domains. This patch modifies our NRPT rule generator to split the list of domains into chunks as necessary, and write a separate rule for each chunk. For compatibility reasons, we continue to use the hard-coded rule ID, but as additional rules are required, we generate new GUIDs. Those GUIDs are stored under the Tailscale registry path so that we know which rules are ours. I made some changes to winutils to add additional helper functions in support of both the code and its test: I added additional registry accessors, and also moved some token accessors from paths to util/winutil. Fixes https://github.com/tailscale/coral/issues/63 Signed-off-by: Aaron Klotz <aaron@tailscale.com>
This commit is contained in:
parent
c16271fb46
commit
b005b79236
@ -63,7 +63,7 @@ tailscale.com/cmd/tailscale dependencies: (generated by github.com/tailscale/dep
|
|||||||
tailscale.com/net/tlsdial from tailscale.com/derp/derphttp
|
tailscale.com/net/tlsdial from tailscale.com/derp/derphttp
|
||||||
tailscale.com/net/tsaddr from tailscale.com/net/interfaces+
|
tailscale.com/net/tsaddr from tailscale.com/net/interfaces+
|
||||||
💣 tailscale.com/net/tshttpproxy from tailscale.com/derp/derphttp+
|
💣 tailscale.com/net/tshttpproxy from tailscale.com/derp/derphttp+
|
||||||
💣 tailscale.com/paths from tailscale.com/cmd/tailscale/cli+
|
tailscale.com/paths from tailscale.com/cmd/tailscale/cli+
|
||||||
tailscale.com/safesocket from tailscale.com/cmd/tailscale/cli+
|
tailscale.com/safesocket from tailscale.com/cmd/tailscale/cli+
|
||||||
tailscale.com/syncs from tailscale.com/net/interfaces+
|
tailscale.com/syncs from tailscale.com/net/interfaces+
|
||||||
tailscale.com/tailcfg from tailscale.com/cmd/tailscale/cli+
|
tailscale.com/tailcfg from tailscale.com/cmd/tailscale/cli+
|
||||||
@ -88,7 +88,7 @@ tailscale.com/cmd/tailscale dependencies: (generated by github.com/tailscale/dep
|
|||||||
W tailscale.com/util/endian from tailscale.com/net/netns
|
W tailscale.com/util/endian from tailscale.com/net/netns
|
||||||
tailscale.com/util/groupmember from tailscale.com/cmd/tailscale/cli
|
tailscale.com/util/groupmember from tailscale.com/cmd/tailscale/cli
|
||||||
tailscale.com/util/lineread from tailscale.com/net/interfaces+
|
tailscale.com/util/lineread from tailscale.com/net/interfaces+
|
||||||
W tailscale.com/util/winutil from tailscale.com/hostinfo
|
W 💣 tailscale.com/util/winutil from tailscale.com/hostinfo+
|
||||||
tailscale.com/version from tailscale.com/cmd/tailscale/cli+
|
tailscale.com/version from tailscale.com/cmd/tailscale/cli+
|
||||||
tailscale.com/version/distro from tailscale.com/cmd/tailscale/cli+
|
tailscale.com/version/distro from tailscale.com/cmd/tailscale/cli+
|
||||||
tailscale.com/wgengine/filter from tailscale.com/types/netmap
|
tailscale.com/wgengine/filter from tailscale.com/types/netmap
|
||||||
|
@ -113,7 +113,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
|
|||||||
L 💣 github.com/vishvananda/netlink/nl from github.com/tailscale/netlink
|
L 💣 github.com/vishvananda/netlink/nl from github.com/tailscale/netlink
|
||||||
L github.com/vishvananda/netns from github.com/tailscale/netlink+
|
L github.com/vishvananda/netns from github.com/tailscale/netlink+
|
||||||
💣 go4.org/intern from inet.af/netaddr
|
💣 go4.org/intern from inet.af/netaddr
|
||||||
💣 go4.org/mem from tailscale.com/client/tailscale+
|
💣 go4.org/mem from tailscale.com/control/controlbase+
|
||||||
go4.org/unsafe/assume-no-moving-gc from go4.org/intern
|
go4.org/unsafe/assume-no-moving-gc from go4.org/intern
|
||||||
W 💣 golang.zx2c4.com/wintun from golang.zx2c4.com/wireguard/tun
|
W 💣 golang.zx2c4.com/wintun from golang.zx2c4.com/wireguard/tun
|
||||||
💣 golang.zx2c4.com/wireguard/conn from golang.zx2c4.com/wireguard/device+
|
💣 golang.zx2c4.com/wireguard/conn from golang.zx2c4.com/wireguard/device+
|
||||||
@ -140,9 +140,9 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
|
|||||||
💣 gvisor.dev/gvisor/pkg/state from gvisor.dev/gvisor/pkg/atomicbitops+
|
💣 gvisor.dev/gvisor/pkg/state from gvisor.dev/gvisor/pkg/atomicbitops+
|
||||||
gvisor.dev/gvisor/pkg/state/wire from gvisor.dev/gvisor/pkg/state
|
gvisor.dev/gvisor/pkg/state/wire from gvisor.dev/gvisor/pkg/state
|
||||||
💣 gvisor.dev/gvisor/pkg/sync from gvisor.dev/gvisor/pkg/linewriter+
|
💣 gvisor.dev/gvisor/pkg/sync from gvisor.dev/gvisor/pkg/linewriter+
|
||||||
gvisor.dev/gvisor/pkg/tcpip from gvisor.dev/gvisor/pkg/tcpip/adapters/gonet+
|
gvisor.dev/gvisor/pkg/tcpip from gvisor.dev/gvisor/pkg/tcpip/header+
|
||||||
gvisor.dev/gvisor/pkg/tcpip/adapters/gonet from tailscale.com/wgengine/netstack
|
gvisor.dev/gvisor/pkg/tcpip/adapters/gonet from tailscale.com/wgengine/netstack
|
||||||
💣 gvisor.dev/gvisor/pkg/tcpip/buffer from gvisor.dev/gvisor/pkg/tcpip/adapters/gonet+
|
💣 gvisor.dev/gvisor/pkg/tcpip/buffer from gvisor.dev/gvisor/pkg/tcpip/header+
|
||||||
gvisor.dev/gvisor/pkg/tcpip/hash/jenkins from gvisor.dev/gvisor/pkg/tcpip/stack+
|
gvisor.dev/gvisor/pkg/tcpip/hash/jenkins from gvisor.dev/gvisor/pkg/tcpip/stack+
|
||||||
gvisor.dev/gvisor/pkg/tcpip/header from gvisor.dev/gvisor/pkg/tcpip/header/parse+
|
gvisor.dev/gvisor/pkg/tcpip/header from gvisor.dev/gvisor/pkg/tcpip/header/parse+
|
||||||
gvisor.dev/gvisor/pkg/tcpip/header/parse from gvisor.dev/gvisor/pkg/tcpip/network/ipv4+
|
gvisor.dev/gvisor/pkg/tcpip/header/parse from gvisor.dev/gvisor/pkg/tcpip/network/ipv4+
|
||||||
@ -155,18 +155,18 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
|
|||||||
gvisor.dev/gvisor/pkg/tcpip/network/ipv6 from tailscale.com/wgengine/netstack
|
gvisor.dev/gvisor/pkg/tcpip/network/ipv6 from tailscale.com/wgengine/netstack
|
||||||
gvisor.dev/gvisor/pkg/tcpip/ports from gvisor.dev/gvisor/pkg/tcpip/stack+
|
gvisor.dev/gvisor/pkg/tcpip/ports from gvisor.dev/gvisor/pkg/tcpip/stack+
|
||||||
gvisor.dev/gvisor/pkg/tcpip/seqnum from gvisor.dev/gvisor/pkg/tcpip/header+
|
gvisor.dev/gvisor/pkg/tcpip/seqnum from gvisor.dev/gvisor/pkg/tcpip/header+
|
||||||
💣 gvisor.dev/gvisor/pkg/tcpip/stack from gvisor.dev/gvisor/pkg/tcpip/adapters/gonet+
|
💣 gvisor.dev/gvisor/pkg/tcpip/stack from gvisor.dev/gvisor/pkg/tcpip/header/parse+
|
||||||
gvisor.dev/gvisor/pkg/tcpip/transport from gvisor.dev/gvisor/pkg/tcpip/transport/icmp+
|
gvisor.dev/gvisor/pkg/tcpip/transport from gvisor.dev/gvisor/pkg/tcpip/transport/internal/network+
|
||||||
gvisor.dev/gvisor/pkg/tcpip/transport/icmp from tailscale.com/wgengine/netstack
|
gvisor.dev/gvisor/pkg/tcpip/transport/icmp from tailscale.com/wgengine/netstack
|
||||||
gvisor.dev/gvisor/pkg/tcpip/transport/internal/network from gvisor.dev/gvisor/pkg/tcpip/transport/icmp+
|
gvisor.dev/gvisor/pkg/tcpip/transport/internal/network from gvisor.dev/gvisor/pkg/tcpip/transport/raw+
|
||||||
gvisor.dev/gvisor/pkg/tcpip/transport/internal/noop from gvisor.dev/gvisor/pkg/tcpip/transport/raw
|
gvisor.dev/gvisor/pkg/tcpip/transport/internal/noop from gvisor.dev/gvisor/pkg/tcpip/transport/raw
|
||||||
gvisor.dev/gvisor/pkg/tcpip/transport/packet from gvisor.dev/gvisor/pkg/tcpip/transport/raw
|
gvisor.dev/gvisor/pkg/tcpip/transport/packet from gvisor.dev/gvisor/pkg/tcpip/transport/raw
|
||||||
gvisor.dev/gvisor/pkg/tcpip/transport/raw from gvisor.dev/gvisor/pkg/tcpip/transport/icmp+
|
gvisor.dev/gvisor/pkg/tcpip/transport/raw from gvisor.dev/gvisor/pkg/tcpip/transport/udp+
|
||||||
💣 gvisor.dev/gvisor/pkg/tcpip/transport/tcp from gvisor.dev/gvisor/pkg/tcpip/adapters/gonet+
|
💣 gvisor.dev/gvisor/pkg/tcpip/transport/tcp from gvisor.dev/gvisor/pkg/tcpip/adapters/gonet+
|
||||||
gvisor.dev/gvisor/pkg/tcpip/transport/tcpconntrack from gvisor.dev/gvisor/pkg/tcpip/stack
|
gvisor.dev/gvisor/pkg/tcpip/transport/tcpconntrack from gvisor.dev/gvisor/pkg/tcpip/stack
|
||||||
gvisor.dev/gvisor/pkg/tcpip/transport/udp from gvisor.dev/gvisor/pkg/tcpip/adapters/gonet+
|
gvisor.dev/gvisor/pkg/tcpip/transport/udp from tailscale.com/net/tstun+
|
||||||
gvisor.dev/gvisor/pkg/waiter from gvisor.dev/gvisor/pkg/context+
|
gvisor.dev/gvisor/pkg/waiter from gvisor.dev/gvisor/pkg/context+
|
||||||
inet.af/netaddr from inet.af/wf+
|
inet.af/netaddr from tailscale.com/control/controlclient+
|
||||||
inet.af/peercred from tailscale.com/ipn/ipnserver
|
inet.af/peercred from tailscale.com/ipn/ipnserver
|
||||||
W 💣 inet.af/wf from tailscale.com/wf
|
W 💣 inet.af/wf from tailscale.com/wf
|
||||||
L nhooyr.io/websocket from tailscale.com/derp/derphttp+
|
L nhooyr.io/websocket from tailscale.com/derp/derphttp+
|
||||||
@ -176,23 +176,23 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
|
|||||||
tailscale.com/atomicfile from tailscale.com/ipn+
|
tailscale.com/atomicfile from tailscale.com/ipn+
|
||||||
LD tailscale.com/chirp from tailscale.com/cmd/tailscaled
|
LD tailscale.com/chirp from tailscale.com/cmd/tailscaled
|
||||||
tailscale.com/client/tailscale from tailscale.com/derp
|
tailscale.com/client/tailscale from tailscale.com/derp
|
||||||
tailscale.com/client/tailscale/apitype from tailscale.com/client/tailscale+
|
tailscale.com/client/tailscale/apitype from tailscale.com/ipn/ipnlocal+
|
||||||
tailscale.com/cmd/tailscaled/childproc from tailscale.com/cmd/tailscaled+
|
tailscale.com/cmd/tailscaled/childproc from tailscale.com/ssh/tailssh+
|
||||||
tailscale.com/control/controlbase from tailscale.com/control/controlclient+
|
tailscale.com/control/controlbase from tailscale.com/control/controlclient+
|
||||||
tailscale.com/control/controlclient from tailscale.com/cmd/tailscaled+
|
tailscale.com/control/controlclient from tailscale.com/ipn/ipnlocal+
|
||||||
tailscale.com/control/controlhttp from tailscale.com/control/controlclient
|
tailscale.com/control/controlhttp from tailscale.com/control/controlclient
|
||||||
tailscale.com/control/controlknobs from tailscale.com/control/controlclient+
|
tailscale.com/control/controlknobs from tailscale.com/control/controlclient+
|
||||||
tailscale.com/derp from tailscale.com/derp/derphttp+
|
tailscale.com/derp from tailscale.com/derp/derphttp+
|
||||||
tailscale.com/derp/derphttp from tailscale.com/cmd/tailscaled+
|
tailscale.com/derp/derphttp from tailscale.com/net/netcheck+
|
||||||
L tailscale.com/derp/wsconn from tailscale.com/derp/derphttp
|
L tailscale.com/derp/wsconn from tailscale.com/derp/derphttp
|
||||||
tailscale.com/disco from tailscale.com/derp+
|
tailscale.com/disco from tailscale.com/derp+
|
||||||
tailscale.com/envknob from tailscale.com/cmd/tailscaled+
|
tailscale.com/envknob from tailscale.com/control/controlclient+
|
||||||
tailscale.com/health from tailscale.com/control/controlclient+
|
tailscale.com/health from tailscale.com/control/controlclient+
|
||||||
tailscale.com/hostinfo from tailscale.com/control/controlclient+
|
tailscale.com/hostinfo from tailscale.com/control/controlclient+
|
||||||
tailscale.com/ipn from tailscale.com/client/tailscale+
|
tailscale.com/ipn from tailscale.com/ipn/ipnlocal+
|
||||||
tailscale.com/ipn/ipnlocal from tailscale.com/ipn/ipnserver+
|
tailscale.com/ipn/ipnlocal from tailscale.com/ssh/tailssh+
|
||||||
tailscale.com/ipn/ipnserver from tailscale.com/cmd/tailscaled
|
tailscale.com/ipn/ipnserver from tailscale.com/cmd/tailscaled
|
||||||
tailscale.com/ipn/ipnstate from tailscale.com/client/tailscale+
|
tailscale.com/ipn/ipnstate from tailscale.com/control/controlclient+
|
||||||
tailscale.com/ipn/localapi from tailscale.com/ipn/ipnserver
|
tailscale.com/ipn/localapi from tailscale.com/ipn/ipnserver
|
||||||
tailscale.com/ipn/policy from tailscale.com/ipn/ipnlocal
|
tailscale.com/ipn/policy from tailscale.com/ipn/ipnlocal
|
||||||
tailscale.com/ipn/store from tailscale.com/cmd/tailscaled
|
tailscale.com/ipn/store from tailscale.com/cmd/tailscaled
|
||||||
@ -203,41 +203,41 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
|
|||||||
tailscale.com/log/filelogger from tailscale.com/logpolicy
|
tailscale.com/log/filelogger from tailscale.com/logpolicy
|
||||||
tailscale.com/log/logheap from tailscale.com/control/controlclient
|
tailscale.com/log/logheap from tailscale.com/control/controlclient
|
||||||
tailscale.com/logpolicy from tailscale.com/cmd/tailscaled+
|
tailscale.com/logpolicy from tailscale.com/cmd/tailscaled+
|
||||||
tailscale.com/logtail from tailscale.com/cmd/tailscaled+
|
tailscale.com/logtail from tailscale.com/control/controlclient+
|
||||||
tailscale.com/logtail/backoff from tailscale.com/cmd/tailscaled+
|
tailscale.com/logtail/backoff from tailscale.com/control/controlclient+
|
||||||
tailscale.com/logtail/filch from tailscale.com/logpolicy
|
tailscale.com/logtail/filch from tailscale.com/logpolicy
|
||||||
💣 tailscale.com/metrics from tailscale.com/derp+
|
💣 tailscale.com/metrics from tailscale.com/derp+
|
||||||
tailscale.com/net/dns from tailscale.com/cmd/tailscaled+
|
tailscale.com/net/dns from tailscale.com/ipn/ipnlocal+
|
||||||
tailscale.com/net/dns/publicdns from tailscale.com/net/dns/resolver
|
tailscale.com/net/dns/publicdns from tailscale.com/net/dns/resolver
|
||||||
tailscale.com/net/dns/resolvconffile from tailscale.com/net/dns+
|
tailscale.com/net/dns/resolvconffile from tailscale.com/net/dns+
|
||||||
tailscale.com/net/dns/resolver from tailscale.com/ipn/ipnlocal+
|
tailscale.com/net/dns/resolver from tailscale.com/ipn/ipnlocal+
|
||||||
tailscale.com/net/dnscache from tailscale.com/control/controlclient+
|
tailscale.com/net/dnscache from tailscale.com/control/controlclient+
|
||||||
tailscale.com/net/dnsfallback from tailscale.com/control/controlclient+
|
tailscale.com/net/dnsfallback from tailscale.com/control/controlclient+
|
||||||
tailscale.com/net/flowtrack from tailscale.com/net/packet+
|
tailscale.com/net/flowtrack from tailscale.com/net/packet+
|
||||||
💣 tailscale.com/net/interfaces from tailscale.com/cmd/tailscaled+
|
💣 tailscale.com/net/interfaces from tailscale.com/control/controlclient+
|
||||||
tailscale.com/net/netcheck from tailscale.com/wgengine/magicsock
|
tailscale.com/net/netcheck from tailscale.com/wgengine/magicsock
|
||||||
tailscale.com/net/neterror from tailscale.com/net/dns/resolver+
|
tailscale.com/net/neterror from tailscale.com/net/dns/resolver+
|
||||||
tailscale.com/net/netknob from tailscale.com/logpolicy+
|
tailscale.com/net/netknob from tailscale.com/net/netns+
|
||||||
tailscale.com/net/netns from tailscale.com/cmd/tailscaled+
|
tailscale.com/net/netns from tailscale.com/derp/derphttp+
|
||||||
💣 tailscale.com/net/netstat from tailscale.com/ipn/ipnserver
|
💣 tailscale.com/net/netstat from tailscale.com/ipn/ipnserver
|
||||||
tailscale.com/net/netutil from tailscale.com/ipn/ipnlocal+
|
tailscale.com/net/netutil from tailscale.com/ipn/ipnlocal+
|
||||||
tailscale.com/net/packet from tailscale.com/net/tstun+
|
tailscale.com/net/packet from tailscale.com/net/tstun+
|
||||||
tailscale.com/net/portmapper from tailscale.com/cmd/tailscaled+
|
tailscale.com/net/portmapper from tailscale.com/net/netcheck+
|
||||||
tailscale.com/net/proxymux from tailscale.com/cmd/tailscaled
|
tailscale.com/net/proxymux from tailscale.com/cmd/tailscaled
|
||||||
tailscale.com/net/socks5 from tailscale.com/cmd/tailscaled
|
tailscale.com/net/socks5 from tailscale.com/cmd/tailscaled
|
||||||
tailscale.com/net/stun from tailscale.com/net/netcheck+
|
tailscale.com/net/stun from tailscale.com/net/netcheck+
|
||||||
tailscale.com/net/tlsdial from tailscale.com/control/controlclient+
|
tailscale.com/net/tlsdial from tailscale.com/control/controlclient+
|
||||||
tailscale.com/net/tsaddr from tailscale.com/ipn+
|
tailscale.com/net/tsaddr from tailscale.com/ipn+
|
||||||
tailscale.com/net/tsdial from tailscale.com/cmd/tailscaled+
|
tailscale.com/net/tsdial from tailscale.com/control/controlclient+
|
||||||
💣 tailscale.com/net/tshttpproxy from tailscale.com/cmd/tailscaled+
|
💣 tailscale.com/net/tshttpproxy from tailscale.com/control/controlclient+
|
||||||
tailscale.com/net/tstun from tailscale.com/cmd/tailscaled+
|
tailscale.com/net/tstun from tailscale.com/net/dns+
|
||||||
💣 tailscale.com/paths from tailscale.com/client/tailscale+
|
tailscale.com/paths from tailscale.com/ipn/ipnlocal+
|
||||||
tailscale.com/portlist from tailscale.com/ipn/ipnlocal
|
tailscale.com/portlist from tailscale.com/ipn/ipnlocal
|
||||||
tailscale.com/safesocket from tailscale.com/client/tailscale+
|
tailscale.com/safesocket from tailscale.com/client/tailscale+
|
||||||
tailscale.com/smallzstd from tailscale.com/ipn/ipnserver+
|
tailscale.com/smallzstd from tailscale.com/ipn/ipnserver+
|
||||||
LD 💣 tailscale.com/ssh/tailssh from tailscale.com/cmd/tailscaled
|
LD 💣 tailscale.com/ssh/tailssh from tailscale.com/cmd/tailscaled
|
||||||
tailscale.com/syncs from tailscale.com/control/controlknobs+
|
tailscale.com/syncs from tailscale.com/control/controlknobs+
|
||||||
tailscale.com/tailcfg from tailscale.com/client/tailscale+
|
tailscale.com/tailcfg from tailscale.com/client/tailscale/apitype+
|
||||||
LD tailscale.com/tempfork/gliderlabs/ssh from tailscale.com/ssh/tailssh
|
LD tailscale.com/tempfork/gliderlabs/ssh from tailscale.com/ssh/tailssh
|
||||||
W tailscale.com/tsconst from tailscale.com/net/interfaces
|
W tailscale.com/tsconst from tailscale.com/net/interfaces
|
||||||
tailscale.com/tstime from tailscale.com/wgengine/magicsock
|
tailscale.com/tstime from tailscale.com/wgengine/magicsock
|
||||||
@ -248,8 +248,8 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
|
|||||||
tailscale.com/types/empty from tailscale.com/control/controlclient+
|
tailscale.com/types/empty from tailscale.com/control/controlclient+
|
||||||
tailscale.com/types/flagtype from tailscale.com/cmd/tailscaled
|
tailscale.com/types/flagtype from tailscale.com/cmd/tailscaled
|
||||||
tailscale.com/types/ipproto from tailscale.com/net/flowtrack+
|
tailscale.com/types/ipproto from tailscale.com/net/flowtrack+
|
||||||
tailscale.com/types/key from tailscale.com/cmd/tailscaled+
|
tailscale.com/types/key from tailscale.com/control/controlbase+
|
||||||
tailscale.com/types/logger from tailscale.com/cmd/tailscaled+
|
tailscale.com/types/logger from tailscale.com/control/controlclient+
|
||||||
tailscale.com/types/netmap from tailscale.com/control/controlclient+
|
tailscale.com/types/netmap from tailscale.com/control/controlclient+
|
||||||
tailscale.com/types/nettype from tailscale.com/wgengine/magicsock
|
tailscale.com/types/nettype from tailscale.com/wgengine/magicsock
|
||||||
tailscale.com/types/opt from tailscale.com/control/controlclient+
|
tailscale.com/types/opt from tailscale.com/control/controlclient+
|
||||||
@ -258,7 +258,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
|
|||||||
tailscale.com/types/preftype from tailscale.com/ipn+
|
tailscale.com/types/preftype from tailscale.com/ipn+
|
||||||
tailscale.com/types/structs from tailscale.com/control/controlclient+
|
tailscale.com/types/structs from tailscale.com/control/controlclient+
|
||||||
tailscale.com/types/views from tailscale.com/ipn/ipnlocal+
|
tailscale.com/types/views from tailscale.com/ipn/ipnlocal+
|
||||||
tailscale.com/util/clientmetric from tailscale.com/cmd/tailscaled+
|
tailscale.com/util/clientmetric from tailscale.com/control/controlclient+
|
||||||
LW tailscale.com/util/cmpver from tailscale.com/net/dns+
|
LW tailscale.com/util/cmpver from tailscale.com/net/dns+
|
||||||
💣 tailscale.com/util/deephash from tailscale.com/ipn/ipnlocal+
|
💣 tailscale.com/util/deephash from tailscale.com/ipn/ipnlocal+
|
||||||
tailscale.com/util/dnsname from tailscale.com/hostinfo+
|
tailscale.com/util/dnsname from tailscale.com/hostinfo+
|
||||||
@ -266,23 +266,23 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
|
|||||||
tailscale.com/util/groupmember from tailscale.com/ipn/ipnserver
|
tailscale.com/util/groupmember from tailscale.com/ipn/ipnserver
|
||||||
tailscale.com/util/lineread from tailscale.com/hostinfo+
|
tailscale.com/util/lineread from tailscale.com/hostinfo+
|
||||||
tailscale.com/util/mak from tailscale.com/control/controlclient+
|
tailscale.com/util/mak from tailscale.com/control/controlclient+
|
||||||
tailscale.com/util/multierr from tailscale.com/cmd/tailscaled+
|
tailscale.com/util/multierr from tailscale.com/control/controlclient+
|
||||||
tailscale.com/util/netconv from tailscale.com/wgengine/magicsock
|
tailscale.com/util/netconv from tailscale.com/wgengine/magicsock
|
||||||
tailscale.com/util/osshare from tailscale.com/cmd/tailscaled+
|
tailscale.com/util/osshare from tailscale.com/ipn/ipnlocal+
|
||||||
tailscale.com/util/pidowner from tailscale.com/ipn/ipnserver
|
tailscale.com/util/pidowner from tailscale.com/ipn/ipnserver
|
||||||
tailscale.com/util/racebuild from tailscale.com/logpolicy
|
tailscale.com/util/racebuild from tailscale.com/logpolicy
|
||||||
tailscale.com/util/systemd from tailscale.com/control/controlclient+
|
tailscale.com/util/systemd from tailscale.com/control/controlclient+
|
||||||
tailscale.com/util/uniq from tailscale.com/wgengine/magicsock
|
tailscale.com/util/uniq from tailscale.com/wgengine/magicsock
|
||||||
tailscale.com/util/winutil from tailscale.com/cmd/tailscaled+
|
💣 tailscale.com/util/winutil from tailscale.com/cmd/tailscaled+
|
||||||
tailscale.com/version from tailscale.com/cmd/tailscaled+
|
tailscale.com/version from tailscale.com/derp+
|
||||||
tailscale.com/version/distro from tailscale.com/cmd/tailscaled+
|
tailscale.com/version/distro from tailscale.com/hostinfo+
|
||||||
W tailscale.com/wf from tailscale.com/cmd/tailscaled
|
W tailscale.com/wf from tailscale.com/cmd/tailscaled
|
||||||
tailscale.com/wgengine from tailscale.com/cmd/tailscaled+
|
tailscale.com/wgengine from tailscale.com/ipn/ipnlocal+
|
||||||
tailscale.com/wgengine/filter from tailscale.com/control/controlclient+
|
tailscale.com/wgengine/filter from tailscale.com/control/controlclient+
|
||||||
tailscale.com/wgengine/magicsock from tailscale.com/ipn/ipnlocal+
|
tailscale.com/wgengine/magicsock from tailscale.com/ipn/ipnlocal+
|
||||||
tailscale.com/wgengine/monitor from tailscale.com/cmd/tailscaled+
|
tailscale.com/wgengine/monitor from tailscale.com/control/controlclient+
|
||||||
tailscale.com/wgengine/netstack from tailscale.com/cmd/tailscaled
|
tailscale.com/wgengine/netstack from tailscale.com/cmd/tailscaled
|
||||||
tailscale.com/wgengine/router from tailscale.com/cmd/tailscaled+
|
tailscale.com/wgengine/router from tailscale.com/ipn/ipnlocal+
|
||||||
tailscale.com/wgengine/wgcfg from tailscale.com/ipn/ipnlocal+
|
tailscale.com/wgengine/wgcfg from tailscale.com/ipn/ipnlocal+
|
||||||
tailscale.com/wgengine/wgcfg/nmcfg from tailscale.com/ipn/ipnlocal
|
tailscale.com/wgengine/wgcfg/nmcfg from tailscale.com/ipn/ipnlocal
|
||||||
tailscale.com/wgengine/wglog from tailscale.com/wgengine
|
tailscale.com/wgengine/wglog from tailscale.com/wgengine
|
||||||
@ -320,7 +320,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
|
|||||||
golang.org/x/sys/cpu from golang.org/x/crypto/blake2b+
|
golang.org/x/sys/cpu from golang.org/x/crypto/blake2b+
|
||||||
LD golang.org/x/sys/unix from github.com/insomniacslk/dhcp/interfaces+
|
LD golang.org/x/sys/unix from github.com/insomniacslk/dhcp/interfaces+
|
||||||
W golang.org/x/sys/windows from github.com/go-ole/go-ole+
|
W golang.org/x/sys/windows from github.com/go-ole/go-ole+
|
||||||
W golang.org/x/sys/windows/registry from golang.zx2c4.com/wireguard/windows/tunnel/winipcfg+
|
W golang.org/x/sys/windows/registry from golang.org/x/sys/windows/svc/eventlog+
|
||||||
W golang.org/x/sys/windows/svc from golang.org/x/sys/windows/svc/mgr+
|
W golang.org/x/sys/windows/svc from golang.org/x/sys/windows/svc/mgr+
|
||||||
W golang.org/x/sys/windows/svc/eventlog from tailscale.com/cmd/tailscaled
|
W golang.org/x/sys/windows/svc/eventlog from tailscale.com/cmd/tailscaled
|
||||||
W golang.org/x/sys/windows/svc/mgr from tailscale.com/cmd/tailscaled
|
W golang.org/x/sys/windows/svc/mgr from tailscale.com/cmd/tailscaled
|
||||||
@ -354,10 +354,10 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
|
|||||||
crypto/sha256 from crypto/tls+
|
crypto/sha256 from crypto/tls+
|
||||||
crypto/sha512 from crypto/ecdsa+
|
crypto/sha512 from crypto/ecdsa+
|
||||||
crypto/subtle from crypto/aes+
|
crypto/subtle from crypto/aes+
|
||||||
crypto/tls from github.com/aws/aws-sdk-go-v2/aws/transport/http+
|
crypto/tls from github.com/tcnksm/go-httpstat+
|
||||||
crypto/x509 from crypto/tls+
|
crypto/x509 from crypto/tls+
|
||||||
crypto/x509/pkix from crypto/x509+
|
crypto/x509/pkix from crypto/x509+
|
||||||
embed from crypto/elliptic+
|
embed from tailscale.com+
|
||||||
encoding from encoding/json+
|
encoding from encoding/json+
|
||||||
encoding/asn1 from crypto/x509+
|
encoding/asn1 from crypto/x509+
|
||||||
encoding/base64 from encoding/json+
|
encoding/base64 from encoding/json+
|
||||||
@ -365,19 +365,19 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
|
|||||||
encoding/hex from crypto/x509+
|
encoding/hex from crypto/x509+
|
||||||
encoding/json from expvar+
|
encoding/json from expvar+
|
||||||
encoding/pem from crypto/tls+
|
encoding/pem from crypto/tls+
|
||||||
encoding/xml from github.com/aws/aws-sdk-go-v2/aws/protocol/xml+
|
encoding/xml from github.com/tailscale/goupnp+
|
||||||
errors from bufio+
|
errors from bufio+
|
||||||
expvar from tailscale.com/derp+
|
expvar from tailscale.com/derp+
|
||||||
flag from tailscale.com/cmd/tailscaled+
|
flag from tailscale.com/control/controlclient+
|
||||||
fmt from compress/flate+
|
fmt from compress/flate+
|
||||||
hash from crypto+
|
hash from crypto+
|
||||||
hash/crc32 from compress/gzip+
|
hash/crc32 from compress/gzip+
|
||||||
hash/fnv from gvisor.dev/gvisor/pkg/tcpip/network/ipv6+
|
hash/fnv from tailscale.com/wgengine/magicsock+
|
||||||
hash/maphash from go4.org/mem
|
hash/maphash from go4.org/mem
|
||||||
html from net/http/pprof+
|
html from tailscale.com/ipn/ipnlocal+
|
||||||
io from bufio+
|
io from bufio+
|
||||||
io/fs from crypto/rand+
|
io/fs from crypto/rand+
|
||||||
io/ioutil from github.com/aws/aws-sdk-go-v2/aws/protocol/query+
|
io/ioutil from github.com/godbus/dbus/v5+
|
||||||
log from expvar+
|
log from expvar+
|
||||||
LD log/syslog from tailscale.com/ssh/tailssh
|
LD log/syslog from tailscale.com/ssh/tailssh
|
||||||
math from compress/flate+
|
math from compress/flate+
|
||||||
@ -394,19 +394,19 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
|
|||||||
net/http/internal from net/http+
|
net/http/internal from net/http+
|
||||||
net/http/pprof from tailscale.com/cmd/tailscaled+
|
net/http/pprof from tailscale.com/cmd/tailscaled+
|
||||||
net/netip from golang.zx2c4.com/wireguard/conn+
|
net/netip from golang.zx2c4.com/wireguard/conn+
|
||||||
net/textproto from github.com/aws/aws-sdk-go-v2/aws/signer/v4+
|
net/textproto from golang.org/x/net/http/httpguts+
|
||||||
net/url from crypto/x509+
|
net/url from crypto/x509+
|
||||||
os from crypto/rand+
|
os from crypto/rand+
|
||||||
os/exec from github.com/aws/aws-sdk-go-v2/credentials/processcreds+
|
os/exec from github.com/coreos/go-iptables/iptables+
|
||||||
os/signal from tailscale.com/cmd/tailscaled+
|
os/signal from tailscale.com/cmd/tailscaled+
|
||||||
os/user from github.com/godbus/dbus/v5+
|
os/user from github.com/godbus/dbus/v5+
|
||||||
path from github.com/aws/aws-sdk-go-v2/credentials/ec2rolecreds+
|
path from github.com/godbus/dbus/v5+
|
||||||
path/filepath from crypto/x509+
|
path/filepath from crypto/x509+
|
||||||
reflect from crypto/x509+
|
reflect from crypto/x509+
|
||||||
regexp from github.com/aws/aws-sdk-go-v2/internal/endpoints/v2+
|
regexp from github.com/coreos/go-iptables/iptables+
|
||||||
regexp/syntax from regexp
|
regexp/syntax from regexp
|
||||||
runtime/debug from github.com/klauspost/compress/zstd+
|
runtime/debug from golang.org/x/sync/singleflight+
|
||||||
runtime/pprof from net/http/pprof+
|
runtime/pprof from tailscale.com/log/logheap+
|
||||||
runtime/trace from net/http/pprof
|
runtime/trace from net/http/pprof
|
||||||
sort from compress/flate+
|
sort from compress/flate+
|
||||||
strconv from compress/flate+
|
strconv from compress/flate+
|
||||||
|
@ -20,18 +20,27 @@
|
|||||||
"tailscale.com/envknob"
|
"tailscale.com/envknob"
|
||||||
"tailscale.com/types/logger"
|
"tailscale.com/types/logger"
|
||||||
"tailscale.com/util/dnsname"
|
"tailscale.com/util/dnsname"
|
||||||
|
"tailscale.com/util/winutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
ipv4RegBase = `SYSTEM\CurrentControlSet\Services\Tcpip\Parameters`
|
ipv4RegBase = `SYSTEM\CurrentControlSet\Services\Tcpip\Parameters`
|
||||||
ipv6RegBase = `SYSTEM\CurrentControlSet\Services\Tcpip6\Parameters`
|
ipv6RegBase = `SYSTEM\CurrentControlSet\Services\Tcpip6\Parameters`
|
||||||
|
|
||||||
// the GUID is randomly generated. At present, Tailscale installs
|
nrptBase = `SYSTEM\CurrentControlSet\Services\Dnscache\Parameters\DnsPolicyConfig\`
|
||||||
// zero or one NRPT rules, so hardcoding a single GUID everywhere
|
|
||||||
// is fine.
|
|
||||||
nrptBase = `SYSTEM\CurrentControlSet\services\Dnscache\Parameters\DnsPolicyConfig\{5abe529b-675b-4486-8459-25a634dacc23}`
|
|
||||||
nrptOverrideDNS = 0x8 // bitmask value for "use the provided override DNS resolvers"
|
nrptOverrideDNS = 0x8 // bitmask value for "use the provided override DNS resolvers"
|
||||||
|
|
||||||
|
// This is the legacy rule ID that previous versions used when we supported
|
||||||
|
// only a single rule. Now that we support multiple rules are required, we
|
||||||
|
// generate their GUIDs and store them under the Tailscale registry key.
|
||||||
|
nrptSingleRuleID = `{5abe529b-675b-4486-8459-25a634dacc23}`
|
||||||
|
// Apparently NRPT rules cannot handle > 50 domains.
|
||||||
|
nrptMaxDomainsPerRule = 50
|
||||||
|
|
||||||
|
// This is the name of the registry value we use to save Rule IDs under
|
||||||
|
// the Tailscale registry key.
|
||||||
|
nrptRuleIDValueName = `NRPTRuleIDs`
|
||||||
|
|
||||||
versionKey = `SOFTWARE\Microsoft\Windows NT\CurrentVersion`
|
versionKey = `SOFTWARE\Microsoft\Windows NT\CurrentVersion`
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -44,6 +53,15 @@ type windowsManager struct {
|
|||||||
wslManager *wslManager
|
wslManager *wslManager
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func loadRuleSubkeyNames() []string {
|
||||||
|
result := winutil.GetRegStrings(nrptRuleIDValueName, nil)
|
||||||
|
if result == nil {
|
||||||
|
// Use the legacy rule ID if none are specified in our registry key
|
||||||
|
result = []string{nrptSingleRuleID}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
func NewOSConfigurator(logf logger.Logf, interfaceName string) (OSConfigurator, error) {
|
func NewOSConfigurator(logf logger.Logf, interfaceName string) (OSConfigurator, error) {
|
||||||
ret := windowsManager{
|
ret := windowsManager{
|
||||||
logf: logf,
|
logf: logf,
|
||||||
@ -59,7 +77,7 @@ func NewOSConfigurator(logf logger.Logf, interfaceName string) (OSConfigurator,
|
|||||||
// boot up. The bootstrap resolver logic will save us, but it
|
// boot up. The bootstrap resolver logic will save us, but it
|
||||||
// slows down start-up a bunch.
|
// slows down start-up a bunch.
|
||||||
if ret.nrptWorks {
|
if ret.nrptWorks {
|
||||||
ret.delKey(nrptBase)
|
ret.delAllRuleKeys()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Log WSL status once at startup.
|
// Log WSL status once at startup.
|
||||||
@ -90,10 +108,26 @@ func (m windowsManager) ifPath(basePath string) string {
|
|||||||
return fmt.Sprintf(`%s\Interfaces\%s`, basePath, m.guid)
|
return fmt.Sprintf(`%s\Interfaces\%s`, basePath, m.guid)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m windowsManager) delKey(path string) error {
|
func (m windowsManager) delAllRuleKeys() error {
|
||||||
if err := registry.DeleteKey(registry.LOCAL_MACHINE, path); err != nil && err != registry.ErrNotExist {
|
nrptRuleIDs := loadRuleSubkeyNames()
|
||||||
|
if err := m.delRuleKeys(nrptRuleIDs); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if err := winutil.DeleteRegValue(nrptRuleIDValueName); err != nil {
|
||||||
|
m.logf("Error deleting registry value %q: %v", nrptRuleIDValueName, err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m windowsManager) delRuleKeys(nrptRuleIDs []string) error {
|
||||||
|
for _, rid := range nrptRuleIDs {
|
||||||
|
keyName := nrptBase + rid
|
||||||
|
if err := registry.DeleteKey(registry.LOCAL_MACHINE, keyName); err != nil && err != registry.ErrNotExist {
|
||||||
|
m.logf("Error deleting NRPT rule key %q: %v", keyName, err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,31 +138,91 @@ func delValue(key registry.Key, name string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// setSplitDNS configures an NRPT (Name Resolution Policy Table) rule
|
// setSplitDNS configures one or more NRPT (Name Resolution Policy Table) rules
|
||||||
// to resolve queries for domains using resolvers, rather than the
|
// to resolve queries for domains using resolvers, rather than the
|
||||||
// system's "primary" resolver.
|
// system's "primary" resolver.
|
||||||
//
|
//
|
||||||
// If no resolvers are provided, the Tailscale NRPT rule is deleted.
|
// If no resolvers are provided, the Tailscale NRPT rules are deleted.
|
||||||
func (m windowsManager) setSplitDNS(resolvers []netaddr.IP, domains []dnsname.FQDN) error {
|
func (m windowsManager) setSplitDNS(resolvers []netaddr.IP, domains []dnsname.FQDN) error {
|
||||||
if len(resolvers) == 0 {
|
if len(resolvers) == 0 {
|
||||||
return m.delKey(nrptBase)
|
return m.delAllRuleKeys()
|
||||||
}
|
}
|
||||||
|
|
||||||
servers := make([]string, 0, len(resolvers))
|
servers := make([]string, 0, len(resolvers))
|
||||||
for _, resolver := range resolvers {
|
for _, resolver := range resolvers {
|
||||||
servers = append(servers, resolver.String())
|
servers = append(servers, resolver.String())
|
||||||
}
|
}
|
||||||
doms := make([]string, 0, len(domains))
|
|
||||||
for _, domain := range domains {
|
// NRPT has an undocumented restriction that each rule may only be associated
|
||||||
// NRPT rules must have a leading dot, which is not usual for
|
// with a maximum of 50 domains. If we are setting rules for more domains
|
||||||
// DNS search paths.
|
// than that, we need to split domains into chunks and write out a rule per chunk.
|
||||||
doms = append(doms, "."+domain.WithoutTrailingDot())
|
dq := len(domains) / nrptMaxDomainsPerRule
|
||||||
|
dr := len(domains) % nrptMaxDomainsPerRule
|
||||||
|
|
||||||
|
domainRulesLen := dq
|
||||||
|
if dr > 0 {
|
||||||
|
domainRulesLen++
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nrptRuleIDs := loadRuleSubkeyNames()
|
||||||
|
for len(nrptRuleIDs) < domainRulesLen {
|
||||||
|
guid, err := windows.GenerateGUID()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
nrptRuleIDs = append(nrptRuleIDs, guid.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove any surplus rules that are no longer needed.
|
||||||
|
ruleIDsToRemove := nrptRuleIDs[domainRulesLen:]
|
||||||
|
m.delRuleKeys(ruleIDsToRemove)
|
||||||
|
|
||||||
|
// We need to save the list of rule IDs to our Tailscale registry key so that
|
||||||
|
// we know which rules are ours during subsequent modifications to NRPT rules.
|
||||||
|
ruleIDsToWrite := nrptRuleIDs[:domainRulesLen]
|
||||||
|
if len(ruleIDsToWrite) > 0 {
|
||||||
|
if err := winutil.SetRegStrings(nrptRuleIDValueName, ruleIDsToWrite); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if err := winutil.DeleteRegValue(nrptRuleIDValueName); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
doms := make([]string, 0, nrptMaxDomainsPerRule)
|
||||||
|
for i := 0; i < domainRulesLen; i++ {
|
||||||
|
// Each iteration consumes nrptMaxDomainsPerRule domains...
|
||||||
|
curLen := nrptMaxDomainsPerRule
|
||||||
|
// Except for the final iteration: when we have a remainder, use that instead.
|
||||||
|
if i == domainRulesLen-1 && dr > 0 {
|
||||||
|
curLen = dr
|
||||||
|
}
|
||||||
|
|
||||||
|
// Obtain the slice of domains to consume within the current iteration.
|
||||||
|
start := i * nrptMaxDomainsPerRule
|
||||||
|
end := start + curLen
|
||||||
|
for _, domain := range domains[start:end] {
|
||||||
|
// NRPT rules must have a leading dot, which is not usual for
|
||||||
|
// DNS search paths.
|
||||||
|
doms = append(doms, "."+domain.WithoutTrailingDot())
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := writeNRPTRule(nrptRuleIDs[i], doms, servers); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
doms = doms[:0]
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func writeNRPTRule(ruleID string, doms, servers []string) error {
|
||||||
// CreateKey is actually open-or-create, which suits us fine.
|
// CreateKey is actually open-or-create, which suits us fine.
|
||||||
key, _, err := registry.CreateKey(registry.LOCAL_MACHINE, nrptBase, registry.SET_VALUE)
|
key, _, err := registry.CreateKey(registry.LOCAL_MACHINE, nrptBase+ruleID, registry.SET_VALUE)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("opening %s: %w", nrptBase, err)
|
return fmt.Errorf("opening %s: %w", nrptBase+ruleID, err)
|
||||||
}
|
}
|
||||||
defer key.Close()
|
defer key.Close()
|
||||||
if err := key.SetDWordValue("Version", 1); err != nil {
|
if err := key.SetDWordValue("Version", 1); err != nil {
|
||||||
|
160
net/dns/manager_windows_test.go
Normal file
160
net/dns/manager_windows_test.go
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
// Copyright (c) 2022 Tailscale Inc & AUTHORS All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package dns
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math/rand"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"golang.org/x/sys/windows"
|
||||||
|
"golang.org/x/sys/windows/registry"
|
||||||
|
"inet.af/netaddr"
|
||||||
|
"tailscale.com/util/dnsname"
|
||||||
|
"tailscale.com/util/winutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestManagerWindows(t *testing.T) {
|
||||||
|
if !winutil.IsCurrentProcessElevated() {
|
||||||
|
t.Skipf("test requires running as elevated user")
|
||||||
|
}
|
||||||
|
|
||||||
|
logf := func(format string, args ...any) {
|
||||||
|
t.Logf(format, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
fakeInterface, err := windows.GenerateGUID()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("windows.GenerateGUID: %v\n", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg, err := NewOSConfigurator(logf, fakeInterface.String())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("NewOSConfigurator: %v\n", err)
|
||||||
|
}
|
||||||
|
mgr := cfg.(windowsManager)
|
||||||
|
|
||||||
|
// Upon initialization of cfg, we should not have any NRPT rules
|
||||||
|
ensureNoRules(t)
|
||||||
|
|
||||||
|
resolvers := []netaddr.IP{netaddr.MustParseIP("1.1.1.1")}
|
||||||
|
|
||||||
|
domains := make([]dnsname.FQDN, 0, 2*nrptMaxDomainsPerRule+1)
|
||||||
|
|
||||||
|
r := rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||||
|
const charset = "abcdefghijklmnopqrstuvwxyz"
|
||||||
|
|
||||||
|
// Just generate a bunch of random subdomains
|
||||||
|
for len(domains) < cap(domains) {
|
||||||
|
l := r.Intn(19) + 1
|
||||||
|
b := make([]byte, l)
|
||||||
|
for i, _ := range b {
|
||||||
|
b[i] = charset[r.Intn(len(charset))]
|
||||||
|
}
|
||||||
|
d := string(b) + ".example.com"
|
||||||
|
fqdn, err := dnsname.ToFQDN(d)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("dnsname.ToFQDN: %v\n", err)
|
||||||
|
}
|
||||||
|
domains = append(domains, fqdn)
|
||||||
|
}
|
||||||
|
|
||||||
|
cases := []int{
|
||||||
|
1,
|
||||||
|
50,
|
||||||
|
51,
|
||||||
|
100,
|
||||||
|
101,
|
||||||
|
100,
|
||||||
|
50,
|
||||||
|
1,
|
||||||
|
51,
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, n := range cases {
|
||||||
|
t.Logf("Test case: %d domains\n", n)
|
||||||
|
caseDomains := domains[:n]
|
||||||
|
err := mgr.setSplitDNS(resolvers, caseDomains)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("setSplitDNS: %v\n", err)
|
||||||
|
}
|
||||||
|
validateRegistry(t, caseDomains)
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Logf("Test case: nil resolver\n")
|
||||||
|
err = mgr.setSplitDNS(nil, domains)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("setSplitDNS: %v\n", err)
|
||||||
|
}
|
||||||
|
ensureNoRules(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ensureNoRules(t *testing.T) {
|
||||||
|
ruleIDs := winutil.GetRegStrings(nrptRuleIDValueName, nil)
|
||||||
|
if ruleIDs != nil {
|
||||||
|
t.Errorf("%s: %v, want nil\n", nrptRuleIDValueName, ruleIDs)
|
||||||
|
}
|
||||||
|
|
||||||
|
legacyKeyPath := nrptBase + nrptSingleRuleID
|
||||||
|
key, err := registry.OpenKey(registry.LOCAL_MACHINE, legacyKeyPath, registry.READ)
|
||||||
|
if err == nil {
|
||||||
|
key.Close()
|
||||||
|
}
|
||||||
|
if err != registry.ErrNotExist {
|
||||||
|
t.Errorf("%s: %q, want %q\n", legacyKeyPath, err, registry.ErrNotExist)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func validateRegistry(t *testing.T, domains []dnsname.FQDN) {
|
||||||
|
q := len(domains) / nrptMaxDomainsPerRule
|
||||||
|
r := len(domains) % nrptMaxDomainsPerRule
|
||||||
|
numRules := q
|
||||||
|
if r > 0 {
|
||||||
|
numRules++
|
||||||
|
}
|
||||||
|
|
||||||
|
ruleIDs := winutil.GetRegStrings(nrptRuleIDValueName, nil)
|
||||||
|
if ruleIDs == nil {
|
||||||
|
ruleIDs = []string{nrptSingleRuleID}
|
||||||
|
} else if len(ruleIDs) != numRules {
|
||||||
|
t.Errorf("%s for %d domains: %d, want %d\n", nrptRuleIDValueName, len(domains), len(ruleIDs), numRules)
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, ruleID := range ruleIDs {
|
||||||
|
savedDomains, err := getSavedDomainsForRule(ruleID)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("getSavedDomainsForRule(%q): %v\n", ruleID, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
start := i * nrptMaxDomainsPerRule
|
||||||
|
end := start + nrptMaxDomainsPerRule
|
||||||
|
if i == len(ruleIDs)-1 && r > 0 {
|
||||||
|
end = start + r
|
||||||
|
}
|
||||||
|
|
||||||
|
checkDomains := domains[start:end]
|
||||||
|
if len(checkDomains) != len(savedDomains) {
|
||||||
|
t.Errorf("len(checkDomains) != len(savedDomains): %d, want %d\n", len(savedDomains), len(checkDomains))
|
||||||
|
}
|
||||||
|
for j, cd := range checkDomains {
|
||||||
|
sd := strings.TrimPrefix(savedDomains[j], ".")
|
||||||
|
if string(cd.WithoutTrailingDot()) != sd {
|
||||||
|
t.Errorf("checkDomain differs savedDomain: %s, want %s\n", sd, cd.WithoutTrailingDot())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getSavedDomainsForRule(ruleID string) ([]string, error) {
|
||||||
|
keyPath := nrptBase + ruleID
|
||||||
|
key, err := registry.OpenKey(registry.LOCAL_MACHINE, keyPath, registry.READ)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer key.Close()
|
||||||
|
result, _, err := key.GetStringsValue("Name")
|
||||||
|
return result, err
|
||||||
|
}
|
@ -8,67 +8,11 @@
|
|||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"unsafe"
|
|
||||||
|
|
||||||
"golang.org/x/sys/windows"
|
"golang.org/x/sys/windows"
|
||||||
|
"tailscale.com/util/winutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
func getTokenInfo(token windows.Token, infoClass uint32) ([]byte, error) {
|
|
||||||
var desiredLen uint32
|
|
||||||
err := windows.GetTokenInformation(token, infoClass, nil, 0, &desiredLen)
|
|
||||||
if err != nil && err != windows.ERROR_INSUFFICIENT_BUFFER {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
buf := make([]byte, desiredLen)
|
|
||||||
actualLen := desiredLen
|
|
||||||
err = windows.GetTokenInformation(token, infoClass, &buf[0], desiredLen, &actualLen)
|
|
||||||
return buf, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func getTokenUserInfo(token windows.Token) (*windows.Tokenuser, error) {
|
|
||||||
buf, err := getTokenInfo(token, windows.TokenUser)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return (*windows.Tokenuser)(unsafe.Pointer(&buf[0])), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getTokenPrimaryGroupInfo(token windows.Token) (*windows.Tokenprimarygroup, error) {
|
|
||||||
buf, err := getTokenInfo(token, windows.TokenPrimaryGroup)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return (*windows.Tokenprimarygroup)(unsafe.Pointer(&buf[0])), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type userSids struct {
|
|
||||||
User *windows.SID
|
|
||||||
PrimaryGroup *windows.SID
|
|
||||||
}
|
|
||||||
|
|
||||||
func getCurrentUserSids() (*userSids, error) {
|
|
||||||
token, err := windows.OpenCurrentProcessToken()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer token.Close()
|
|
||||||
|
|
||||||
userInfo, err := getTokenUserInfo(token)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
primaryGroup, err := getTokenPrimaryGroupInfo(token)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &userSids{userInfo.User.Sid, primaryGroup.PrimaryGroup}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ensureStateDirPerms applies a restrictive ACL to the directory specified by dirPath.
|
// ensureStateDirPerms applies a restrictive ACL to the directory specified by dirPath.
|
||||||
// It sets the following security attributes on the directory:
|
// It sets the following security attributes on the directory:
|
||||||
// Owner: The user for the current process;
|
// Owner: The user for the current process;
|
||||||
@ -93,7 +37,7 @@ func ensureStateDirPerms(dirPath string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// We need the info for our current user as SIDs
|
// We need the info for our current user as SIDs
|
||||||
sids, err := getCurrentUserSids()
|
sids, err := winutil.GetCurrentUserSIDs()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
"os/exec"
|
"os/exec"
|
||||||
"runtime"
|
"runtime"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
"golang.org/x/sys/windows"
|
"golang.org/x/sys/windows"
|
||||||
"golang.org/x/sys/windows/registry"
|
"golang.org/x/sys/windows/registry"
|
||||||
@ -94,6 +95,70 @@ func getRegStringInternal(subKey, name string) (string, error) {
|
|||||||
return val, nil
|
return val, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetRegStrings looks up a registry value in the local machine path, or returns
|
||||||
|
// the given default if it can't.
|
||||||
|
func GetRegStrings(name string, defval []string) []string {
|
||||||
|
s, err := getRegStringsInternal(regBase, name)
|
||||||
|
if err != nil {
|
||||||
|
return defval
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
func getRegStringsInternal(subKey, name string) ([]string, error) {
|
||||||
|
key, err := registry.OpenKey(registry.LOCAL_MACHINE, subKey, registry.READ)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("registry.OpenKey(%v): %v", subKey, err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer key.Close()
|
||||||
|
|
||||||
|
val, _, err := key.GetStringsValue(name)
|
||||||
|
if err != nil {
|
||||||
|
if err != registry.ErrNotExist {
|
||||||
|
log.Printf("registry.GetStringValue(%v): %v", name, err)
|
||||||
|
}
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return val, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetRegStrings sets a MULTI_SZ value in the in the local machine path
|
||||||
|
// to the strings specified by values.
|
||||||
|
func SetRegStrings(name string, values []string) error {
|
||||||
|
return setRegStringsInternal(regBase, name, values)
|
||||||
|
}
|
||||||
|
|
||||||
|
func setRegStringsInternal(subKey, name string, values []string) error {
|
||||||
|
key, _, err := registry.CreateKey(registry.LOCAL_MACHINE, subKey, registry.SET_VALUE)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("registry.CreateKey(%v): %v", subKey, err)
|
||||||
|
}
|
||||||
|
defer key.Close()
|
||||||
|
|
||||||
|
return key.SetStringsValue(name, values)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteRegValue removes a registry value in the local machine path.
|
||||||
|
func DeleteRegValue(name string) error {
|
||||||
|
return deleteRegValueInternal(regBase, name)
|
||||||
|
}
|
||||||
|
|
||||||
|
func deleteRegValueInternal(subKey, name string) error {
|
||||||
|
key, err := registry.OpenKey(registry.LOCAL_MACHINE, subKey, registry.SET_VALUE)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("registry.OpenKey(%v): %v", subKey, err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer key.Close()
|
||||||
|
|
||||||
|
err = key.DeleteValue(name)
|
||||||
|
if err == registry.ErrNotExist {
|
||||||
|
err = nil
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
func getRegIntegerInternal(subKey, name string) (uint64, error) {
|
func getRegIntegerInternal(subKey, name string) (uint64, error) {
|
||||||
key, err := registry.OpenKey(registry.LOCAL_MACHINE, subKey, registry.READ)
|
key, err := registry.OpenKey(registry.LOCAL_MACHINE, subKey, registry.READ)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -254,3 +319,75 @@ func StartProcessAsCurrentGUIUser(exePath string, extraEnv []string) error {
|
|||||||
func CreateAppMutex(name string) (windows.Handle, error) {
|
func CreateAppMutex(name string) (windows.Handle, error) {
|
||||||
return windows.CreateMutex(nil, false, windows.StringToUTF16Ptr(name))
|
return windows.CreateMutex(nil, false, windows.StringToUTF16Ptr(name))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getTokenInfo(token windows.Token, infoClass uint32) ([]byte, error) {
|
||||||
|
var desiredLen uint32
|
||||||
|
err := windows.GetTokenInformation(token, infoClass, nil, 0, &desiredLen)
|
||||||
|
if err != nil && err != windows.ERROR_INSUFFICIENT_BUFFER {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
buf := make([]byte, desiredLen)
|
||||||
|
actualLen := desiredLen
|
||||||
|
err = windows.GetTokenInformation(token, infoClass, &buf[0], desiredLen, &actualLen)
|
||||||
|
return buf, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func getTokenUserInfo(token windows.Token) (*windows.Tokenuser, error) {
|
||||||
|
buf, err := getTokenInfo(token, windows.TokenUser)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return (*windows.Tokenuser)(unsafe.Pointer(&buf[0])), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getTokenPrimaryGroupInfo(token windows.Token) (*windows.Tokenprimarygroup, error) {
|
||||||
|
buf, err := getTokenInfo(token, windows.TokenPrimaryGroup)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return (*windows.Tokenprimarygroup)(unsafe.Pointer(&buf[0])), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UserSIDs contains the SIDs for a Windows NT token object's associated user
|
||||||
|
// as well as its primary group.
|
||||||
|
type UserSIDs struct {
|
||||||
|
User *windows.SID
|
||||||
|
PrimaryGroup *windows.SID
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetCurrentUserSIDs returns a UserSIDs struct containing SIDs for the
|
||||||
|
// current process' user and primary group.
|
||||||
|
func GetCurrentUserSIDs() (*UserSIDs, error) {
|
||||||
|
token, err := windows.OpenCurrentProcessToken()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer token.Close()
|
||||||
|
|
||||||
|
userInfo, err := getTokenUserInfo(token)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
primaryGroup, err := getTokenPrimaryGroupInfo(token)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &UserSIDs{userInfo.User.Sid, primaryGroup.PrimaryGroup}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsCurrentProcessElevated returns true when the current process is
|
||||||
|
// running with an elevated token, implying Administrator access.
|
||||||
|
func IsCurrentProcessElevated() bool {
|
||||||
|
token, err := windows.OpenCurrentProcessToken()
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
defer token.Close()
|
||||||
|
|
||||||
|
return token.IsElevated()
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user