mirror of
https://github.com/tailscale/tailscale.git
synced 2025-04-16 03:31:39 +00:00
tstest/natlab/vnet: add start of IPv6 support
Updates #13038 Change-Id: Ic3d095f167daf6c7129463e881b18f2e0d5693f5 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
parent
31b5239a2f
commit
b78df4d48a
@ -28,6 +28,7 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"tailscale.com/atomicfile"
|
||||||
"tailscale.com/client/tailscale"
|
"tailscale.com/client/tailscale"
|
||||||
"tailscale.com/hostinfo"
|
"tailscale.com/hostinfo"
|
||||||
"tailscale.com/util/must"
|
"tailscale.com/util/must"
|
||||||
@ -85,13 +86,25 @@ func main() {
|
|||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
if distro.Get() == distro.Gokrazy {
|
if distro.Get() == distro.Gokrazy {
|
||||||
nsRx := regexp.MustCompile(`(?m)^nameserver (.*)`)
|
cmdLine, _ := os.ReadFile("/proc/cmdline")
|
||||||
for t := time.Now(); time.Since(t) < 10*time.Second; time.Sleep(10 * time.Millisecond) {
|
explicitNS := false
|
||||||
all, _ := os.ReadFile("/etc/resolv.conf")
|
for _, s := range strings.Fields(string(cmdLine)) {
|
||||||
if nsRx.Match(all) {
|
if ns, ok := strings.CutPrefix(s, "tta.nameserver="); ok {
|
||||||
|
err := atomicfile.WriteFile("/tmp/resolv.conf", []byte("nameserver "+ns+"\n"), 0644)
|
||||||
|
log.Printf("Wrote /tmp/resolv.conf: %v", err)
|
||||||
|
explicitNS = true
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if !explicitNS {
|
||||||
|
nsRx := regexp.MustCompile(`(?m)^nameserver (.*)`)
|
||||||
|
for t := time.Now(); time.Since(t) < 10*time.Second; time.Sleep(10 * time.Millisecond) {
|
||||||
|
all, _ := os.ReadFile("/etc/resolv.conf")
|
||||||
|
if nsRx.Match(all) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Printf("Tailscale Test Agent running.")
|
log.Printf("Tailscale Test Agent running.")
|
||||||
|
@ -2,12 +2,18 @@
|
|||||||
|
|
||||||
echo "Type 'C-a c' to enter monitor; q to quit."
|
echo "Type 'C-a c' to enter monitor; q to quit."
|
||||||
|
|
||||||
|
# If the USE_V6 environment is set to 1, set the nameserver explicitly to.
|
||||||
|
EXTRA_ARG=""
|
||||||
|
if [ "$USE_V6" = "1" ]; then
|
||||||
|
EXTRA_ARG="tta.nameserver=2411::411"
|
||||||
|
fi
|
||||||
|
|
||||||
set -eux
|
set -eux
|
||||||
qemu-system-x86_64 -M microvm,isa-serial=off \
|
qemu-system-x86_64 -M microvm,isa-serial=off \
|
||||||
-m 1G \
|
-m 1G \
|
||||||
-nodefaults -no-user-config -nographic \
|
-nodefaults -no-user-config -nographic \
|
||||||
-kernel $HOME/src/github.com/tailscale/gokrazy-kernel/vmlinuz \
|
-kernel $HOME/src/github.com/tailscale/gokrazy-kernel/vmlinuz \
|
||||||
-append "console=hvc0 root=PARTUUID=60c24cc1-f3f9-427a-8199-76baa2d60001/PARTNROFF=1 ro init=/gokrazy/init panic=10 oops=panic pci=off nousb tsc=unstable clocksource=hpet tailscale-tta=1 tailscaled.env=TS_DEBUG_RAW_DISCO=1" \
|
-append "console=hvc0 root=PARTUUID=60c24cc1-f3f9-427a-8199-76baa2d60001/PARTNROFF=1 ro init=/gokrazy/init panic=10 oops=panic pci=off nousb tsc=unstable clocksource=hpet tailscale-tta=1 tailscaled.env=TS_DEBUG_RAW_DISCO=1 ${EXTRA_ARG}" \
|
||||||
-drive id=blk0,file=$HOME/src/tailscale.com/gokrazy/natlabapp.img,format=raw \
|
-drive id=blk0,file=$HOME/src/tailscale.com/gokrazy/natlabapp.img,format=raw \
|
||||||
-device virtio-blk-device,drive=blk0 \
|
-device virtio-blk-device,drive=blk0 \
|
||||||
-device virtio-rng-device \
|
-device virtio-rng-device \
|
||||||
|
@ -25,10 +25,12 @@ var (
|
|||||||
listen = flag.String("listen", "/tmp/qemu.sock", "path to listen on")
|
listen = flag.String("listen", "/tmp/qemu.sock", "path to listen on")
|
||||||
nat = flag.String("nat", "easy", "type of NAT to use")
|
nat = flag.String("nat", "easy", "type of NAT to use")
|
||||||
nat2 = flag.String("nat2", "hard", "type of NAT to use for second network")
|
nat2 = flag.String("nat2", "hard", "type of NAT to use for second network")
|
||||||
portmap = flag.Bool("portmap", false, "enable portmapping")
|
portmap = flag.Bool("portmap", false, "enable portmapping; requires --v4")
|
||||||
dgram = flag.Bool("dgram", false, "enable datagram mode; for use with macOS Hypervisor.Framework and VZFileHandleNetworkDeviceAttachment")
|
dgram = flag.Bool("dgram", false, "enable datagram mode; for use with macOS Hypervisor.Framework and VZFileHandleNetworkDeviceAttachment")
|
||||||
blend = flag.Bool("blend", true, "blend reality (controlplane.tailscale.com and DERPs) into the virtual network")
|
blend = flag.Bool("blend", true, "blend reality (controlplane.tailscale.com and DERPs) into the virtual network")
|
||||||
pcapFile = flag.String("pcap", "", "if non-empty, filename to write pcap")
|
pcapFile = flag.String("pcap", "", "if non-empty, filename to write pcap")
|
||||||
|
v4 = flag.Bool("v4", true, "enable IPv4")
|
||||||
|
v6 = flag.Bool("v6", true, "enable IPv6")
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@ -61,9 +63,18 @@ func main() {
|
|||||||
var c vnet.Config
|
var c vnet.Config
|
||||||
c.SetPCAPFile(*pcapFile)
|
c.SetPCAPFile(*pcapFile)
|
||||||
c.SetBlendReality(*blend)
|
c.SetBlendReality(*blend)
|
||||||
node1 := c.AddNode(c.AddNetwork("2.1.1.1", "192.168.1.1/24", vnet.NAT(*nat)))
|
|
||||||
|
var net1opt = []any{vnet.NAT(*nat)}
|
||||||
|
if *v4 {
|
||||||
|
net1opt = append(net1opt, "2.1.1.1", "192.168.1.1/24")
|
||||||
|
}
|
||||||
|
if *v6 {
|
||||||
|
net1opt = append(net1opt, "2000:52::1/64")
|
||||||
|
}
|
||||||
|
|
||||||
|
node1 := c.AddNode(c.AddNetwork(net1opt...))
|
||||||
c.AddNode(c.AddNetwork("2.2.2.2", "10.2.0.1/16", vnet.NAT(*nat2)))
|
c.AddNode(c.AddNetwork("2.2.2.2", "10.2.0.1/16", vnet.NAT(*nat2)))
|
||||||
if *portmap {
|
if *portmap && *v4 {
|
||||||
node1.Network().AddService(vnet.NATPMP)
|
node1.Network().AddService(vnet.NATPMP)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,8 +83,10 @@ func main() {
|
|||||||
log.Fatalf("newServer: %v", err)
|
log.Fatalf("newServer: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := s.PopulateDERPMapIPs(); err != nil {
|
if *blend {
|
||||||
log.Printf("warning: ignoring failure to populate DERP map: %v", err)
|
if err := s.PopulateDERPMapIPs(); err != nil {
|
||||||
|
log.Printf("warning: ignoring failure to populate DERP map: %v", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
s.WriteStartingBanner(os.Stdout)
|
s.WriteStartingBanner(os.Stdout)
|
||||||
|
@ -95,6 +95,10 @@ func findKernelPath(goMod string) (string, error) {
|
|||||||
|
|
||||||
type addNodeFunc func(c *vnet.Config) *vnet.Node // returns nil to omit test
|
type addNodeFunc func(c *vnet.Config) *vnet.Node // returns nil to omit test
|
||||||
|
|
||||||
|
func v6cidr(n int) string {
|
||||||
|
return fmt.Sprintf("2000:%d::1/64", n)
|
||||||
|
}
|
||||||
|
|
||||||
func easy(c *vnet.Config) *vnet.Node {
|
func easy(c *vnet.Config) *vnet.Node {
|
||||||
n := c.NumNodes() + 1
|
n := c.NumNodes() + 1
|
||||||
return c.AddNode(c.AddNetwork(
|
return c.AddNode(c.AddNetwork(
|
||||||
@ -102,6 +106,20 @@ func easy(c *vnet.Config) *vnet.Node {
|
|||||||
fmt.Sprintf("192.168.%d.1/24", n), vnet.EasyNAT))
|
fmt.Sprintf("192.168.%d.1/24", n), vnet.EasyNAT))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func easyAnd6(c *vnet.Config) *vnet.Node {
|
||||||
|
n := c.NumNodes() + 1
|
||||||
|
return c.AddNode(c.AddNetwork(
|
||||||
|
fmt.Sprintf("2.%d.%d.%d", n, n, n), // public IP
|
||||||
|
fmt.Sprintf("192.168.%d.1/24", n),
|
||||||
|
v6cidr(n),
|
||||||
|
vnet.EasyNAT))
|
||||||
|
}
|
||||||
|
|
||||||
|
func just6(c *vnet.Config) *vnet.Node {
|
||||||
|
n := c.NumNodes() + 1
|
||||||
|
return c.AddNode(c.AddNetwork(v6cidr(n))) // public IPv6 prefix
|
||||||
|
}
|
||||||
|
|
||||||
// easy + host firewall
|
// easy + host firewall
|
||||||
func easyFW(c *vnet.Config) *vnet.Node {
|
func easyFW(c *vnet.Config) *vnet.Node {
|
||||||
n := c.NumNodes() + 1
|
n := c.NumNodes() + 1
|
||||||
@ -255,6 +273,11 @@ func (nt *natTest) runTest(node1, node2 addNodeFunc) pingRoute {
|
|||||||
for _, e := range node.Env() {
|
for _, e := range node.Env() {
|
||||||
fmt.Fprintf(&envBuf, " tailscaled.env=%s=%s", e.Key, e.Value)
|
fmt.Fprintf(&envBuf, " tailscaled.env=%s=%s", e.Key, e.Value)
|
||||||
}
|
}
|
||||||
|
sysLogAddr := net.JoinHostPort(vnet.FakeSyslogIPv4().String(), "995")
|
||||||
|
if node.IsV6Only() {
|
||||||
|
fmt.Fprintf(&envBuf, " tta.nameserver=%s", vnet.FakeDNSIPv6())
|
||||||
|
sysLogAddr = net.JoinHostPort(vnet.FakeSyslogIPv6().String(), "995")
|
||||||
|
}
|
||||||
envStr := envBuf.String()
|
envStr := envBuf.String()
|
||||||
|
|
||||||
cmd := exec.Command("qemu-system-x86_64",
|
cmd := exec.Command("qemu-system-x86_64",
|
||||||
@ -262,7 +285,7 @@ func (nt *natTest) runTest(node1, node2 addNodeFunc) pingRoute {
|
|||||||
"-m", "384M",
|
"-m", "384M",
|
||||||
"-nodefaults", "-no-user-config", "-nographic",
|
"-nodefaults", "-no-user-config", "-nographic",
|
||||||
"-kernel", nt.kernel,
|
"-kernel", nt.kernel,
|
||||||
"-append", "console=hvc0 root=PARTUUID=60c24cc1-f3f9-427a-8199-76baa2d60001/PARTNROFF=1 ro init=/gokrazy/init panic=10 oops=panic pci=off nousb tsc=unstable clocksource=hpet gokrazy.remote_syslog.target=52.52.0.9:995 tailscale-tta=1"+envStr,
|
"-append", "console=hvc0 root=PARTUUID=60c24cc1-f3f9-427a-8199-76baa2d60001/PARTNROFF=1 ro init=/gokrazy/init panic=10 oops=panic pci=off nousb tsc=unstable clocksource=hpet gokrazy.remote_syslog.target="+sysLogAddr+" tailscale-tta=1"+envStr,
|
||||||
"-drive", "id=blk0,file="+disk+",format=qcow2",
|
"-drive", "id=blk0,file="+disk+",format=qcow2",
|
||||||
"-device", "virtio-blk-device,drive=blk0",
|
"-device", "virtio-blk-device,drive=blk0",
|
||||||
"-netdev", "stream,id=net0,addr.type=unix,addr.path="+sockAddr,
|
"-netdev", "stream,id=net0,addr.type=unix,addr.path="+sockAddr,
|
||||||
@ -445,6 +468,20 @@ func TestEasyEasy(t *testing.T) {
|
|||||||
nt.want(routeDirect)
|
nt.want(routeDirect)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestJustIPv6(t *testing.T) {
|
||||||
|
t.Skip("TODO: get this working")
|
||||||
|
nt := newNatTest(t)
|
||||||
|
nt.runTest(just6, just6)
|
||||||
|
nt.want(routeDirect)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEasy4AndJust6(t *testing.T) {
|
||||||
|
t.Skip("TODO: get this working")
|
||||||
|
nt := newNatTest(t)
|
||||||
|
nt.runTest(easyAnd6, just6)
|
||||||
|
nt.want(routeDirect)
|
||||||
|
}
|
||||||
|
|
||||||
func TestSameLAN(t *testing.T) {
|
func TestSameLAN(t *testing.T) {
|
||||||
nt := newNatTest(t)
|
nt := newNatTest(t)
|
||||||
nt.runTest(easy, sameLAN)
|
nt.runTest(easy, sameLAN)
|
||||||
|
@ -132,6 +132,7 @@ type TailscaledEnv struct {
|
|||||||
func (c *Config) AddNetwork(opts ...any) *Network {
|
func (c *Config) AddNetwork(opts ...any) *Network {
|
||||||
num := len(c.networks)
|
num := len(c.networks)
|
||||||
n := &Network{
|
n := &Network{
|
||||||
|
num: num + 1,
|
||||||
mac: MAC{0x52, 0xee, 0xee, 0xee, 0xee, byte(num) + 1}, // 52=TS then 0xee for 'etwork
|
mac: MAC{0x52, 0xee, 0xee, 0xee, 0xee, byte(num) + 1}, // 52=TS then 0xee for 'etwork
|
||||||
}
|
}
|
||||||
c.networks = append(c.networks, n)
|
c.networks = append(c.networks, n)
|
||||||
@ -139,9 +140,15 @@ func (c *Config) AddNetwork(opts ...any) *Network {
|
|||||||
switch o := o.(type) {
|
switch o := o.(type) {
|
||||||
case string:
|
case string:
|
||||||
if ip, err := netip.ParseAddr(o); err == nil {
|
if ip, err := netip.ParseAddr(o); err == nil {
|
||||||
n.wanIP = ip
|
n.wanIP4 = ip
|
||||||
} else if ip, err := netip.ParsePrefix(o); err == nil {
|
} else if ip, err := netip.ParsePrefix(o); err == nil {
|
||||||
n.lanIP = ip
|
// If the prefix is IPv4, treat it as the router's internal IPv4 address + CIDR.
|
||||||
|
// If the prefix is IPv6, treat it as the router's WAN IPv6 + CIDR (typically a /64).
|
||||||
|
if ip.Addr().Is4() {
|
||||||
|
n.lanIP4 = ip
|
||||||
|
} else if ip.Addr().Is6() {
|
||||||
|
n.wanIP6 = ip
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if n.err == nil {
|
if n.err == nil {
|
||||||
n.err = fmt.Errorf("unknown string option %q", o)
|
n.err = fmt.Errorf("unknown string option %q", o)
|
||||||
@ -208,6 +215,21 @@ func (n *Node) SetVerboseSyslog(v bool) {
|
|||||||
n.verboseSyslog = v
|
n.verboseSyslog = v
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsV6Only reports whether this node is only connected to IPv6 networks.
|
||||||
|
func (n *Node) IsV6Only() bool {
|
||||||
|
for _, net := range n.nets {
|
||||||
|
if net.CanV4() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, net := range n.nets {
|
||||||
|
if net.CanV6() {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// Network returns the first network this node is connected to,
|
// Network returns the first network this node is connected to,
|
||||||
// or nil if none.
|
// or nil if none.
|
||||||
func (n *Node) Network() *Network {
|
func (n *Node) Network() *Network {
|
||||||
@ -219,12 +241,15 @@ func (n *Node) Network() *Network {
|
|||||||
|
|
||||||
// Network is the configuration of a network in the virtual network.
|
// Network is the configuration of a network in the virtual network.
|
||||||
type Network struct {
|
type Network struct {
|
||||||
|
num int // 1-based
|
||||||
mac MAC // MAC address of the router/gateway
|
mac MAC // MAC address of the router/gateway
|
||||||
natType NAT
|
natType NAT
|
||||||
|
|
||||||
wanIP netip.Addr
|
wanIP6 netip.Prefix // global unicast router in host bits; CIDR is /64 delegated to LAN
|
||||||
lanIP netip.Prefix
|
|
||||||
nodes []*Node
|
wanIP4 netip.Addr // IPv4 WAN IP, if any
|
||||||
|
lanIP4 netip.Prefix
|
||||||
|
nodes []*Node
|
||||||
|
|
||||||
svcs set.Set[NetworkService]
|
svcs set.Set[NetworkService]
|
||||||
|
|
||||||
@ -232,6 +257,14 @@ type Network struct {
|
|||||||
err error // carried error
|
err error // carried error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (n *Network) CanV4() bool {
|
||||||
|
return n.lanIP4.IsValid() || n.wanIP4.IsValid()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *Network) CanV6() bool {
|
||||||
|
return n.wanIP6.IsValid()
|
||||||
|
}
|
||||||
|
|
||||||
func (n *Network) CanTakeMoreNodes() bool {
|
func (n *Network) CanTakeMoreNodes() bool {
|
||||||
if n.natType == One2OneNAT {
|
if n.natType == One2OneNAT {
|
||||||
return len(n.nodes) == 0
|
return len(n.nodes) == 0
|
||||||
@ -282,24 +315,43 @@ func (s *Server) initFromConfig(c *Config) error {
|
|||||||
if conf.err != nil {
|
if conf.err != nil {
|
||||||
return conf.err
|
return conf.err
|
||||||
}
|
}
|
||||||
if !conf.lanIP.IsValid() {
|
if !conf.lanIP4.IsValid() && !conf.wanIP6.IsValid() {
|
||||||
conf.lanIP = netip.MustParsePrefix("192.168.0.0/24")
|
conf.lanIP4 = netip.MustParsePrefix("192.168.0.0/24")
|
||||||
}
|
}
|
||||||
n := &network{
|
n := &network{
|
||||||
s: s,
|
num: conf.num,
|
||||||
mac: conf.mac,
|
s: s,
|
||||||
portmap: conf.svcs.Contains(NATPMP), // TODO: expand network.portmap
|
mac: conf.mac,
|
||||||
wanIP: conf.wanIP,
|
portmap: conf.svcs.Contains(NATPMP), // TODO: expand network.portmap
|
||||||
lanIP: conf.lanIP,
|
wanIP6: conf.wanIP6,
|
||||||
nodesByIP: map[netip.Addr]*node{},
|
v4: conf.lanIP4.IsValid(),
|
||||||
logf: logger.WithPrefix(log.Printf, fmt.Sprintf("[net-%v] ", conf.mac)),
|
v6: conf.wanIP6.IsValid(),
|
||||||
|
wanIP4: conf.wanIP4,
|
||||||
|
lanIP4: conf.lanIP4,
|
||||||
|
nodesByIP: map[netip.Addr]*node{},
|
||||||
|
nodesByMAC: map[MAC]*node{},
|
||||||
|
logf: logger.WithPrefix(log.Printf, fmt.Sprintf("[net-%v] ", conf.mac)),
|
||||||
}
|
}
|
||||||
netOfConf[conf] = n
|
netOfConf[conf] = n
|
||||||
s.networks.Add(n)
|
s.networks.Add(n)
|
||||||
if _, ok := s.networkByWAN[conf.wanIP]; ok {
|
if conf.wanIP4.IsValid() {
|
||||||
return fmt.Errorf("two networks have the same WAN IP %v; Anycast not (yet?) supported", conf.wanIP)
|
if conf.wanIP4.Is6() {
|
||||||
|
return fmt.Errorf("invalid IPv6 address in wanIP")
|
||||||
|
}
|
||||||
|
if _, ok := s.networkByWAN.Lookup(conf.wanIP4); ok {
|
||||||
|
return fmt.Errorf("two networks have the same WAN IP %v; Anycast not (yet?) supported", conf.wanIP4)
|
||||||
|
}
|
||||||
|
s.networkByWAN.Insert(netip.PrefixFrom(conf.wanIP4, 32), n)
|
||||||
|
}
|
||||||
|
if conf.wanIP6.IsValid() {
|
||||||
|
if conf.wanIP6.Addr().Is4() {
|
||||||
|
return fmt.Errorf("invalid IPv4 address in wanIP6")
|
||||||
|
}
|
||||||
|
if _, ok := s.networkByWAN.LookupPrefix(conf.wanIP6); ok {
|
||||||
|
return fmt.Errorf("two networks have the same WAN IPv6 %v; Anycast not (yet?) supported", conf.wanIP6)
|
||||||
|
}
|
||||||
|
s.networkByWAN.Insert(conf.wanIP6, n)
|
||||||
}
|
}
|
||||||
s.networkByWAN[conf.wanIP] = n
|
|
||||||
n.lanInterfaceID = must.Get(s.pcapWriter.AddInterface(pcapgo.NgInterface{
|
n.lanInterfaceID = must.Get(s.pcapWriter.AddInterface(pcapgo.NgInterface{
|
||||||
Name: fmt.Sprintf("network%d-lan", i+1),
|
Name: fmt.Sprintf("network%d-lan", i+1),
|
||||||
LinkType: layers.LinkTypeIPv4,
|
LinkType: layers.LinkTypeIPv4,
|
||||||
@ -330,13 +382,16 @@ func (s *Server) initFromConfig(c *Config) error {
|
|||||||
s.nodes = append(s.nodes, n)
|
s.nodes = append(s.nodes, n)
|
||||||
s.nodeByMAC[n.mac] = n
|
s.nodeByMAC[n.mac] = n
|
||||||
|
|
||||||
// Allocate a lanIP for the node. Use the network's CIDR and use final
|
if n.net.v4 {
|
||||||
// octet 101 (for first node), 102, etc. The node number comes from the
|
// Allocate a lanIP for the node. Use the network's CIDR and use final
|
||||||
// last octent of the MAC address (0-based)
|
// octet 101 (for first node), 102, etc. The node number comes from the
|
||||||
ip4 := n.net.lanIP.Addr().As4()
|
// last octent of the MAC address (0-based)
|
||||||
ip4[3] = 100 + n.mac[5]
|
ip4 := n.net.lanIP4.Addr().As4()
|
||||||
n.lanIP = netip.AddrFrom4(ip4)
|
ip4[3] = 100 + n.mac[5]
|
||||||
n.net.nodesByIP[n.lanIP] = n
|
n.lanIP = netip.AddrFrom4(ip4)
|
||||||
|
n.net.nodesByIP[n.lanIP] = n
|
||||||
|
}
|
||||||
|
n.net.nodesByMAC[n.mac] = n
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now that nodes are populated, set up NAT:
|
// Now that nodes are populated, set up NAT:
|
||||||
|
@ -11,7 +11,7 @@ import (
|
|||||||
var vips = map[string]virtualIP{} // DNS name => details
|
var vips = map[string]virtualIP{} // DNS name => details
|
||||||
|
|
||||||
var (
|
var (
|
||||||
fakeDNS = newVIP("dns", "4.11.4.11", "2000:4:11::4:11")
|
fakeDNS = newVIP("dns", "4.11.4.11", "2411::411")
|
||||||
fakeProxyControlplane = newVIP("controlplane.tailscale.com", 1)
|
fakeProxyControlplane = newVIP("controlplane.tailscale.com", 1)
|
||||||
fakeTestAgent = newVIP("test-driver.tailscale", 2)
|
fakeTestAgent = newVIP("test-driver.tailscale", 2)
|
||||||
fakeControl = newVIP("control.tailscale", 3)
|
fakeControl = newVIP("control.tailscale", 3)
|
||||||
@ -31,6 +31,18 @@ func (v virtualIP) Match(a netip.Addr) bool {
|
|||||||
return v.v4 == a.Unmap() || v.v6 == a
|
return v.v4 == a.Unmap() || v.v6 == a
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FakeDNSIPv4 returns the fake DNS IPv4 address.
|
||||||
|
func FakeDNSIPv4() netip.Addr { return fakeDNS.v4 }
|
||||||
|
|
||||||
|
// FakeDNSIPv6 returns the fake DNS IPv6 address.
|
||||||
|
func FakeDNSIPv6() netip.Addr { return fakeDNS.v6 }
|
||||||
|
|
||||||
|
// FakeSyslogIPv4 returns the fake syslog IPv4 address.
|
||||||
|
func FakeSyslogIPv4() netip.Addr { return fakeSyslog.v4 }
|
||||||
|
|
||||||
|
// FakeSyslogIPv6 returns the fake syslog IPv6 address.
|
||||||
|
func FakeSyslogIPv6() netip.Addr { return fakeSyslog.v6 }
|
||||||
|
|
||||||
// newVIP returns a new virtual IP.
|
// newVIP returns a new virtual IP.
|
||||||
//
|
//
|
||||||
// opts may be an IPv4 an IPv6 (in string form) or an int (bounded by uint8) to
|
// opts may be an IPv4 an IPv6 (in string form) or an int (bounded by uint8) to
|
||||||
@ -67,8 +79,14 @@ func newVIP(name string, opts ...any) (v virtualIP) {
|
|||||||
}
|
}
|
||||||
if !v.v6.IsValid() && v.v4.IsValid() {
|
if !v.v6.IsValid() && v.v4.IsValid() {
|
||||||
// Map 1.2.3.4 to 2052::0102:0304
|
// Map 1.2.3.4 to 2052::0102:0304
|
||||||
a := [16]byte{0: 2, 2: 5, 3: 2} // 2052::
|
// But make 52.52.0.x map to 2052::x
|
||||||
copy(a[12:], v.v4.AsSlice())
|
a := [16]byte{0: 0x20, 1: 0x52} // 2052::
|
||||||
|
v4 := v.v4.As4()
|
||||||
|
if v4[0] == 52 && v4[1] == 52 && v4[2] == 0 {
|
||||||
|
a[15] = v4[3]
|
||||||
|
} else {
|
||||||
|
copy(a[12:], v.v4.AsSlice())
|
||||||
|
}
|
||||||
v.v6 = netip.AddrFrom16(a)
|
v.v6 = netip.AddrFrom16(a)
|
||||||
}
|
}
|
||||||
for _, b := range vips {
|
for _, b := range vips {
|
||||||
|
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user