|
|
|
@ -31,6 +31,7 @@ import (
|
|
|
|
|
"os/exec"
|
|
|
|
|
"strconv"
|
|
|
|
|
"sync"
|
|
|
|
|
"sync/atomic"
|
|
|
|
|
"time"
|
|
|
|
|
|
|
|
|
|
"github.com/google/gopacket"
|
|
|
|
@ -58,6 +59,7 @@ import (
|
|
|
|
|
"tailscale.com/types/key"
|
|
|
|
|
"tailscale.com/types/logger"
|
|
|
|
|
"tailscale.com/util/mak"
|
|
|
|
|
"tailscale.com/util/must"
|
|
|
|
|
"tailscale.com/util/set"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
@ -444,6 +446,7 @@ func (n *network) MACOfIP(ip netip.Addr) (_ MAC, ok bool) {
|
|
|
|
|
|
|
|
|
|
type node struct {
|
|
|
|
|
mac MAC
|
|
|
|
|
id int
|
|
|
|
|
net *network
|
|
|
|
|
lanIP netip.Addr // must be in net.lanIP prefix + unique in net
|
|
|
|
|
}
|
|
|
|
@ -474,6 +477,8 @@ func newDERPServer() *derpServer {
|
|
|
|
|
type Server struct {
|
|
|
|
|
shutdownCtx context.Context
|
|
|
|
|
shutdownCancel context.CancelFunc
|
|
|
|
|
shuttingDown atomic.Bool
|
|
|
|
|
wg sync.WaitGroup
|
|
|
|
|
blendReality bool
|
|
|
|
|
|
|
|
|
|
derpIPs set.Set[netip.Addr]
|
|
|
|
@ -485,6 +490,7 @@ type Server struct {
|
|
|
|
|
|
|
|
|
|
control *testcontrol.Server
|
|
|
|
|
derps []*derpServer
|
|
|
|
|
pcapWriter *pcapWriter
|
|
|
|
|
|
|
|
|
|
mu sync.Mutex
|
|
|
|
|
agentConnWaiter map[*node]chan<- struct{} // signaled after added to set
|
|
|
|
@ -562,7 +568,13 @@ func New(c *Config) (*Server, error) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (s *Server) Close() {
|
|
|
|
|
if shutdown := s.shuttingDown.Swap(true); !shutdown {
|
|
|
|
|
s.shutdownCancel()
|
|
|
|
|
if s.pcapWriter != nil {
|
|
|
|
|
s.pcapWriter.Close()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
s.wg.Wait()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (s *Server) HWAddr(mac MAC) net.HardwareAddr {
|
|
|
|
@ -601,11 +613,20 @@ const (
|
|
|
|
|
|
|
|
|
|
// serveConn serves a single connection from a client.
|
|
|
|
|
func (s *Server) ServeUnixConn(uc *net.UnixConn, proto Protocol) {
|
|
|
|
|
if s.shuttingDown.Load() {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
s.wg.Add(1)
|
|
|
|
|
defer s.wg.Done()
|
|
|
|
|
context.AfterFunc(s.shutdownCtx, func() {
|
|
|
|
|
uc.SetDeadline(time.Now())
|
|
|
|
|
})
|
|
|
|
|
log.Printf("Got conn %T %p", uc, uc)
|
|
|
|
|
defer uc.Close()
|
|
|
|
|
|
|
|
|
|
bw := bufio.NewWriterSize(uc, 2<<10)
|
|
|
|
|
var writeMu sync.Mutex
|
|
|
|
|
var srcNode *node
|
|
|
|
|
writePkt := func(pkt []byte) {
|
|
|
|
|
if pkt == nil {
|
|
|
|
|
return
|
|
|
|
@ -626,10 +647,20 @@ func (s *Server) ServeUnixConn(uc *net.UnixConn, proto Protocol) {
|
|
|
|
|
if err := bw.Flush(); err != nil {
|
|
|
|
|
log.Printf("Flush: %v", err)
|
|
|
|
|
}
|
|
|
|
|
if s.pcapWriter != nil {
|
|
|
|
|
ci := gopacket.CaptureInfo{
|
|
|
|
|
Timestamp: time.Now(),
|
|
|
|
|
CaptureLength: len(pkt),
|
|
|
|
|
Length: len(pkt),
|
|
|
|
|
}
|
|
|
|
|
if srcNode != nil {
|
|
|
|
|
ci.InterfaceIndex = srcNode.id
|
|
|
|
|
}
|
|
|
|
|
must.Do(s.pcapWriter.WritePacket(ci, pkt))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
buf := make([]byte, 16<<10)
|
|
|
|
|
var srcNode *node
|
|
|
|
|
var netw *network // non-nil after first packet
|
|
|
|
|
for {
|
|
|
|
|
var packetRaw []byte
|
|
|
|
@ -686,6 +717,17 @@ func (s *Server) ServeUnixConn(uc *net.UnixConn, proto Protocol) {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if s.pcapWriter != nil {
|
|
|
|
|
ci := gopacket.CaptureInfo{
|
|
|
|
|
Timestamp: time.Now(),
|
|
|
|
|
CaptureLength: len(packetRaw),
|
|
|
|
|
Length: len(packetRaw),
|
|
|
|
|
}
|
|
|
|
|
if srcNode != nil {
|
|
|
|
|
ci.InterfaceIndex = srcNode.id
|
|
|
|
|
}
|
|
|
|
|
must.Do(s.pcapWriter.WritePacket(ci, packetRaw))
|
|
|
|
|
}
|
|
|
|
|
netw.HandleEthernetPacket(ep)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -840,7 +882,6 @@ func (n *network) WriteUDPPacketNoNAT(p UDPPacket) {
|
|
|
|
|
// IP may be the router's IP, or an internet (routed) IP.
|
|
|
|
|
func (n *network) HandleEthernetIPv4PacketForRouter(ep EthernetPacket) {
|
|
|
|
|
packet := ep.gp
|
|
|
|
|
writePkt := n.writeEth
|
|
|
|
|
|
|
|
|
|
v4, ok := packet.Layer(layers.LayerTypeIPv4).(*layers.IPv4)
|
|
|
|
|
if !ok {
|
|
|
|
@ -857,7 +898,7 @@ func (n *network) HandleEthernetIPv4PacketForRouter(ep EthernetPacket) {
|
|
|
|
|
n.logf("createDHCPResponse: %v", err)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
writePkt(res)
|
|
|
|
|
n.writeEth(res)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -874,7 +915,7 @@ func (n *network) HandleEthernetIPv4PacketForRouter(ep EthernetPacket) {
|
|
|
|
|
n.logf("createDNSResponse: %v", err)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
writePkt(res)
|
|
|
|
|
n.writeEth(res)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|