net/tstun: use /10 as subnet for TAP mode; read IP from netmap

Few changes to resolve TODOs in the code:
- Instead of using a hardcoded IP, get it from the netmap.
- Use 100.100.100.100 as the gateway IP
- Use the /10 CGNAT range instead of a random /24

Updates #2589

Signed-off-by: Maisem Ali <maisem@tailscale.com>
pull/13049/merge
Maisem Ali 2 days ago committed by Maisem Ali
parent d4d21a0bbf
commit 85241f8408

@ -25,6 +25,7 @@ import (
"gvisor.dev/gvisor/pkg/tcpip/transport/udp" "gvisor.dev/gvisor/pkg/tcpip/transport/udp"
"tailscale.com/net/netaddr" "tailscale.com/net/netaddr"
"tailscale.com/net/packet" "tailscale.com/net/packet"
"tailscale.com/net/tsaddr"
"tailscale.com/syncs" "tailscale.com/syncs"
"tailscale.com/types/ipproto" "tailscale.com/types/ipproto"
"tailscale.com/types/logger" "tailscale.com/types/logger"
@ -158,7 +159,7 @@ func (t *tapDevice) handleTAPFrame(ethBuf []byte) bool {
// If the client's asking about their own IP, tell them it's // If the client's asking about their own IP, tell them it's
// their own MAC. TODO(bradfitz): remove String allocs. // their own MAC. TODO(bradfitz): remove String allocs.
if net.IP(req.ProtocolAddressTarget()).String() == theClientIP { if net.IP(req.ProtocolAddressTarget()).String() == t.clientIPv4.Load() {
copy(res.HardwareAddressSender(), ethSrcMAC) copy(res.HardwareAddressSender(), ethSrcMAC)
} else { } else {
copy(res.HardwareAddressSender(), ourMAC[:]) copy(res.HardwareAddressSender(), ourMAC[:])
@ -178,9 +179,12 @@ func (t *tapDevice) handleTAPFrame(ethBuf []byte) bool {
} }
} }
// TODO(bradfitz): remove these hard-coded values and move from a /24 to a /10 CGNAT as the range. var (
const theClientIP = "100.70.145.3" // TODO: make dynamic from netmap // routerIP is the IP address of the DHCP server.
const routerIP = "100.70.145.1" // must be in same netmask (currently hack at /24) as theClientIP routerIP = net.ParseIP(tsaddr.TailscaleServiceIPString)
// cgnatNetMask is the netmask of the 100.64.0.0/10 CGNAT range.
cgnatNetMask = net.IPMask(net.ParseIP("255.192.0.0").To4())
)
// handleDHCPRequest handles receiving a raw TAP ethernet frame and reports whether // handleDHCPRequest handles receiving a raw TAP ethernet frame and reports whether
// it's been handled as a DHCP request. That is, it reports whether the frame should // it's been handled as a DHCP request. That is, it reports whether the frame should
@ -228,17 +232,22 @@ func (t *tapDevice) handleDHCPRequest(ethBuf []byte) bool {
} }
switch dp.MessageType() { switch dp.MessageType() {
case dhcpv4.MessageTypeDiscover: case dhcpv4.MessageTypeDiscover:
ips := t.clientIPv4.Load()
if ips == "" {
t.logf("tap: DHCP no client IP")
return consumePacket
}
offer, err := dhcpv4.New( offer, err := dhcpv4.New(
dhcpv4.WithReply(dp), dhcpv4.WithReply(dp),
dhcpv4.WithMessageType(dhcpv4.MessageTypeOffer), dhcpv4.WithMessageType(dhcpv4.MessageTypeOffer),
dhcpv4.WithRouter(net.ParseIP(routerIP)), // the default route dhcpv4.WithRouter(routerIP), // the default route
dhcpv4.WithDNS(net.ParseIP("100.100.100.100")), dhcpv4.WithDNS(routerIP),
dhcpv4.WithServerIP(net.ParseIP("100.100.100.100")), // TODO: what is this? dhcpv4.WithServerIP(routerIP), // TODO: what is this?
dhcpv4.WithOption(dhcpv4.OptServerIdentifier(net.ParseIP("100.100.100.100"))), dhcpv4.WithOption(dhcpv4.OptServerIdentifier(routerIP)),
dhcpv4.WithYourIP(net.ParseIP(theClientIP)), dhcpv4.WithYourIP(net.ParseIP(ips)),
dhcpv4.WithLeaseTime(3600), // hour works dhcpv4.WithLeaseTime(3600), // hour works
//dhcpv4.WithHwAddr(ethSrcMAC), //dhcpv4.WithHwAddr(ethSrcMAC),
dhcpv4.WithNetmask(net.IPMask(net.ParseIP("255.255.255.0").To4())), // TODO: wrong dhcpv4.WithNetmask(cgnatNetMask),
//dhcpv4.WithTransactionID(dp.TransactionID), //dhcpv4.WithTransactionID(dp.TransactionID),
) )
if err != nil { if err != nil {
@ -258,16 +267,21 @@ func (t *tapDevice) handleDHCPRequest(ethBuf []byte) bool {
t.logf("tap: wrote DHCP OFFER %v, %v", n, err) t.logf("tap: wrote DHCP OFFER %v, %v", n, err)
} }
case dhcpv4.MessageTypeRequest: case dhcpv4.MessageTypeRequest:
ips := t.clientIPv4.Load()
if ips == "" {
t.logf("tap: DHCP no client IP")
return consumePacket
}
ack, err := dhcpv4.New( ack, err := dhcpv4.New(
dhcpv4.WithReply(dp), dhcpv4.WithReply(dp),
dhcpv4.WithMessageType(dhcpv4.MessageTypeAck), dhcpv4.WithMessageType(dhcpv4.MessageTypeAck),
dhcpv4.WithDNS(net.ParseIP("100.100.100.100")), dhcpv4.WithDNS(routerIP),
dhcpv4.WithRouter(net.ParseIP(routerIP)), // the default route dhcpv4.WithRouter(routerIP), // the default route
dhcpv4.WithServerIP(net.ParseIP("100.100.100.100")), // TODO: what is this? dhcpv4.WithServerIP(routerIP), // TODO: what is this?
dhcpv4.WithOption(dhcpv4.OptServerIdentifier(net.ParseIP("100.100.100.100"))), dhcpv4.WithOption(dhcpv4.OptServerIdentifier(routerIP)),
dhcpv4.WithYourIP(net.ParseIP(theClientIP)), // Hello world dhcpv4.WithYourIP(net.ParseIP(ips)), // Hello world
dhcpv4.WithLeaseTime(3600), // hour works dhcpv4.WithLeaseTime(3600), // hour works
dhcpv4.WithNetmask(net.IPMask(net.ParseIP("255.255.255.0").To4())), dhcpv4.WithNetmask(cgnatNetMask),
) )
if err != nil { if err != nil {
t.logf("error building DHCP ack: %v", err) t.logf("error building DHCP ack: %v", err)
@ -368,15 +382,23 @@ func newTAPDevice(logf logger.Logf, fd int, tapName string) (tun.Device, error)
} }
type tapDevice struct { type tapDevice struct {
file *os.File file *os.File
logf func(format string, args ...any) logf func(format string, args ...any)
events chan tun.Event events chan tun.Event
name string name string
closeOnce sync.Once closeOnce sync.Once
clientIPv4 syncs.AtomicValue[string]
destMACAtomic syncs.AtomicValue[[6]byte] destMACAtomic syncs.AtomicValue[[6]byte]
} }
var _ setIPer = (*tapDevice)(nil)
func (t *tapDevice) SetIP(ipV4, ipV6TODO netip.Addr) error {
t.clientIPv4.Store(ipV4.String())
return nil
}
func (t *tapDevice) File() *os.File { func (t *tapDevice) File() *os.File {
return t.file return t.file
} }

@ -802,10 +802,19 @@ func (pc *peerConfigTable) outboundPacketIsJailed(p *packet.Parsed) bool {
return c.jailed return c.jailed
} }
type setIPer interface {
// SetIP sets the IP addresses of the TAP device.
SetIP(ipV4, ipV6 netip.Addr) error
}
// SetWGConfig is called when a new NetworkMap is received. // SetWGConfig is called when a new NetworkMap is received.
func (t *Wrapper) SetWGConfig(wcfg *wgcfg.Config) { func (t *Wrapper) SetWGConfig(wcfg *wgcfg.Config) {
if t.isTAP {
if sip, ok := t.tdev.(setIPer); ok {
sip.SetIP(findV4(wcfg.Addresses), findV6(wcfg.Addresses))
}
}
cfg := peerConfigTableFromWGConfig(wcfg) cfg := peerConfigTableFromWGConfig(wcfg)
old := t.peerConfig.Swap(cfg) old := t.peerConfig.Swap(cfg)
if !reflect.DeepEqual(old, cfg) { if !reflect.DeepEqual(old, cfg) {
t.logf("peer config: %v", cfg) t.logf("peer config: %v", cfg)

Loading…
Cancel
Save