tunnel.go 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439
  1. package aerotun
  2. import (
  3. "crypto/rand"
  4. "encoding/binary"
  5. "errors"
  6. "fmt"
  7. "log"
  8. "net"
  9. "net/netip"
  10. "sync"
  11. "sync/atomic"
  12. "time"
  13. "github.com/pierrec/lz4/v4"
  14. )
  15. const peerTimeout = 65 * time.Second
  16. type TunnelRunner struct {
  17. secure *secureProtocol
  18. allowed []netip.Prefix
  19. effectiveMTU atomic.Int64
  20. configuredMTU int
  21. mu sync.RWMutex
  22. cfg TunnelInstance
  23. dev VirtualDevice
  24. udpConn *net.UDPConn
  25. protocol *protocolState
  26. remoteAddr *net.UDPAddr
  27. stopChan chan struct{}
  28. closed bool
  29. wg sync.WaitGroup
  30. routes routeManager
  31. lastHandshake time.Time
  32. lastError string
  33. rxBytes, txBytes, rawBytesIn, rawBytesOut, wireBytesIn, wireBytesOut uint64
  34. savedBytes, packetsRx, packetsTx, compressedPackets, rawPackets uint64
  35. droppedPackets, authFailures, replayDrops uint64
  36. dropInvalidOutgoing, dropMissingSession, dropSendFailure uint64
  37. dropInvalidIncoming, dropSourcePolicy, dropInterfaceWrite uint64
  38. }
  39. func (t *TunnelRunner) recordDrop(kind *uint64, count uint64) {
  40. atomic.AddUint64(&t.droppedPackets, count)
  41. atomic.AddUint64(kind, count)
  42. }
  43. func NewTunnelRunner(cfg TunnelInstance) (*TunnelRunner, error) {
  44. if err := validateConfig(&cfg); err != nil {
  45. return nil, err
  46. }
  47. configuredMTU := cfg.MTU
  48. var remote *net.UDPAddr
  49. var err error
  50. if cfg.RemoteEndpoint != "" {
  51. remote, err = net.ResolveUDPAddr("udp", cfg.RemoteEndpoint)
  52. if err != nil {
  53. return nil, fmt.Errorf("resolve remote endpoint: %w", err)
  54. }
  55. if remote.IP == nil || remote.IP.IsUnspecified() || remote.IP.IsMulticast() {
  56. return nil, fmt.Errorf("remote endpoint must be a unicast IP")
  57. }
  58. }
  59. var p *protocolState
  60. var secure *secureProtocol
  61. if cfg.Protocol == 3 {
  62. secure, err = newSecureProtocol(cfg)
  63. } else {
  64. p, err = newProtocol(cfg.PSK)
  65. }
  66. if err != nil {
  67. return nil, err
  68. }
  69. if remote != nil {
  70. cfg.MTU, err = underlayMTUForHeader(cfg.MTU, remote.IP, packetHeaderSize(cfg.Protocol))
  71. if err != nil {
  72. return nil, err
  73. }
  74. }
  75. if local, _, _ := net.ParseCIDR(cfg.LocalAddress); local.To4() == nil && cfg.MTU < 1280 {
  76. return nil, fmt.Errorf("underlay cannot carry IPv6 tunnel MTU 1280")
  77. }
  78. dev, err := CreateDevice(cfg.Name, cfg.MTU, cfg.LocalAddress)
  79. if err != nil {
  80. return nil, fmt.Errorf("create interface: %w", err)
  81. }
  82. if err = configurePeer(dev, cfg); err != nil {
  83. _ = dev.Close()
  84. return nil, err
  85. }
  86. conn, err := net.ListenUDP("udp", &net.UDPAddr{Port: cfg.ListenPort})
  87. if err != nil {
  88. _ = dev.Close()
  89. return nil, fmt.Errorf("bind UDP: %w", err)
  90. }
  91. bufferSize := 4 << 20
  92. if cfg.Protocol == 3 {
  93. bufferSize = 1 << 20
  94. }
  95. _ = conn.SetReadBuffer(bufferSize)
  96. _ = conn.SetWriteBuffer(bufferSize)
  97. runner := &TunnelRunner{secure: secure, cfg: cfg, configuredMTU: configuredMTU, dev: dev, udpConn: conn, protocol: p, remoteAddr: remote, stopChan: make(chan struct{}), routes: routeManager{run: runIP}}
  98. for _, p := range cfg.AllowedIPs {
  99. prefix, _ := netip.ParsePrefix(p)
  100. runner.allowed = append(runner.allowed, prefix.Masked())
  101. }
  102. runner.effectiveMTU.Store(int64(cfg.MTU))
  103. return runner, nil
  104. }
  105. func (t *TunnelRunner) Start() error {
  106. if t.cfg.DefaultRoute {
  107. if err := t.routes.install(t.cfg.Name, t.remoteAddr.IP); err != nil {
  108. return err
  109. }
  110. }
  111. t.wg.Add(3)
  112. go func() { defer t.wg.Done(); t.txLoop() }()
  113. go func() { defer t.wg.Done(); t.rxLoop() }()
  114. go func() { defer t.wg.Done(); t.keepaliveLoop() }()
  115. log.Printf("[AeroTUN] %s started: protocol v%d, UDP %s, MTU %d", t.cfg.Name, t.cfg.Protocol, t.udpConn.LocalAddr(), t.cfg.MTU)
  116. return nil
  117. }
  118. func (t *TunnelRunner) Stop() {
  119. t.mu.Lock()
  120. if t.closed {
  121. t.mu.Unlock()
  122. return
  123. }
  124. t.closed = true
  125. close(t.stopChan)
  126. t.mu.Unlock()
  127. _ = t.udpConn.Close()
  128. _ = t.dev.Close()
  129. t.wg.Wait()
  130. t.routes.cleanup()
  131. }
  132. func (t *TunnelRunner) setError(err error) {
  133. t.mu.Lock()
  134. t.lastError = err.Error()
  135. t.mu.Unlock()
  136. }
  137. func (t *TunnelRunner) target() *net.UDPAddr {
  138. t.mu.RLock()
  139. defer t.mu.RUnlock()
  140. return t.remoteAddr
  141. }
  142. func (t *TunnelRunner) send(flags byte, payload []byte, target *net.UDPAddr, session sessionID) error {
  143. if t.secure != nil {
  144. var packet [64]byte
  145. var nonce [24]byte
  146. if target == nil {
  147. return errSession
  148. }
  149. b, err := t.secure.sealInto(packet[:0], &nonce, flags, payload)
  150. if err != nil {
  151. return err
  152. }
  153. n, err := t.udpConn.WriteToUDP(b, target)
  154. if err == nil {
  155. atomic.AddUint64(&t.wireBytesOut, uint64(n))
  156. }
  157. return err
  158. }
  159. if target == nil {
  160. return errSession
  161. }
  162. b, err := t.protocol.seal(flags, payload, session)
  163. if err != nil {
  164. return err
  165. }
  166. n, err := t.udpConn.WriteToUDP(b, target)
  167. if err == nil {
  168. atomic.AddUint64(&t.wireBytesOut, uint64(n))
  169. }
  170. return err
  171. }
  172. func (t *TunnelRunner) sendControl(flags byte, target *net.UDPAddr, session sessionID) error {
  173. payload := make([]byte, 2)
  174. binary.BigEndian.PutUint16(payload, uint16(t.effectiveMTU.Load()))
  175. return t.send(flags, payload, target, session)
  176. }
  177. func (t *TunnelRunner) txLoop() {
  178. if t.secure != nil {
  179. t.txLoopSecure()
  180. return
  181. }
  182. buf := make([]byte, maxPacketSize)
  183. var comp *adaptiveCompressor
  184. if t.cfg.Compression {
  185. comp = newAdaptiveCompressor(maxPacketSize)
  186. }
  187. for {
  188. n, err := t.dev.Read(buf)
  189. if err != nil {
  190. select {
  191. case <-t.stopChan:
  192. return
  193. default:
  194. }
  195. t.setError(fmt.Errorf("interface read: %w", err))
  196. time.Sleep(10 * time.Millisecond)
  197. continue
  198. }
  199. if n == 0 {
  200. continue
  201. }
  202. if n > int(t.effectiveMTU.Load()) || !validIPPacket(buf[:n]) {
  203. atomic.AddUint64(&t.droppedPackets, 1)
  204. t.setError(fmt.Errorf("invalid or oversized interface packet (%d bytes, MTU %d)", n, t.effectiveMTU.Load()))
  205. continue
  206. }
  207. payload := buf[:n]
  208. flags := byte(0)
  209. if comp != nil {
  210. if compressed, ok := comp.Compress(payload); ok {
  211. payload = compressed
  212. flags = FlagCompressedLZ4
  213. }
  214. }
  215. if err := t.send(flags, payload, t.target(), zeroSession); err != nil {
  216. atomic.AddUint64(&t.droppedPackets, 1)
  217. if !errors.Is(err, errSession) {
  218. t.setError(fmt.Errorf("UDP send: %w", err))
  219. }
  220. continue
  221. }
  222. atomic.AddUint64(&t.txBytes, uint64(n))
  223. atomic.AddUint64(&t.rawBytesOut, uint64(n))
  224. atomic.AddUint64(&t.packetsTx, 1)
  225. if flags == FlagCompressedLZ4 {
  226. atomic.AddUint64(&t.compressedPackets, 1)
  227. atomic.AddUint64(&t.savedBytes, uint64(n-len(payload)))
  228. } else {
  229. atomic.AddUint64(&t.rawPackets, 1)
  230. }
  231. }
  232. }
  233. func (t *TunnelRunner) rxLoop() {
  234. if t.secure != nil {
  235. t.rxLoopSecure()
  236. return
  237. }
  238. buf := make([]byte, maxPacketSize)
  239. decomp := make([]byte, maxPacketSize)
  240. for {
  241. n, src, err := t.udpConn.ReadFromUDP(buf)
  242. if err != nil {
  243. select {
  244. case <-t.stopChan:
  245. return
  246. default:
  247. }
  248. t.setError(err)
  249. continue
  250. }
  251. // A client pins its configured endpoint; servers support authenticated roaming.
  252. if t.cfg.Mode == "client" && !udpAddrsEqual(t.target(), src) {
  253. continue
  254. }
  255. payload, flags, sender, _, err := t.protocol.open(buf[:n])
  256. if err != nil {
  257. if errors.Is(err, errReplay) {
  258. atomic.AddUint64(&t.replayDrops, 1)
  259. } else {
  260. atomic.AddUint64(&t.authFailures, 1)
  261. }
  262. continue
  263. }
  264. atomic.AddUint64(&t.wireBytesIn, uint64(n))
  265. if flags == flagHello {
  266. if err := t.sendControl(flagAck, src, sender); err != nil {
  267. t.setError(err)
  268. }
  269. continue
  270. }
  271. // A replayable HELLO must not change MTU or connection state. Only
  272. // packets bound to our current boot/session may change the dataplane.
  273. previousMTU := t.effectiveMTU.Load()
  274. if flags == flagAck || flags == flagConfirm || flags == FlagKeepalive {
  275. if err := t.adjustMTU(src.IP, int(binary.BigEndian.Uint16(payload))); err != nil {
  276. t.setError(err)
  277. continue
  278. }
  279. }
  280. t.mu.Lock()
  281. t.remoteAddr = src
  282. t.lastHandshake = time.Now()
  283. t.mu.Unlock()
  284. if flags == flagAck {
  285. if err := t.sendControl(flagConfirm, src, sender); err != nil {
  286. t.setError(err)
  287. }
  288. continue
  289. }
  290. if flags == FlagKeepalive || flags == flagConfirm {
  291. // Propagate a lower underlay/path MTU immediately, including when
  292. // it was discovered only after receiving the final confirmation.
  293. if t.effectiveMTU.Load() < previousMTU {
  294. if err := t.sendControl(FlagKeepalive, src, sender); err != nil {
  295. t.setError(err)
  296. }
  297. }
  298. continue
  299. }
  300. if flags == FlagCompressedLZ4 {
  301. size, err := lz4.UncompressBlock(payload, decomp[:int(t.effectiveMTU.Load())])
  302. if err != nil || size == 0 {
  303. atomic.AddUint64(&t.droppedPackets, 1)
  304. continue
  305. }
  306. payload = decomp[:size]
  307. }
  308. if len(payload) > int(t.effectiveMTU.Load()) || !validIPPacket(payload) {
  309. atomic.AddUint64(&t.droppedPackets, 1)
  310. continue
  311. }
  312. wrote, err := t.dev.Write(payload)
  313. if err != nil || wrote != len(payload) {
  314. atomic.AddUint64(&t.droppedPackets, 1)
  315. t.setError(fmt.Errorf("interface write: %d/%d bytes, %v", wrote, len(payload), err))
  316. continue
  317. }
  318. atomic.AddUint64(&t.rxBytes, uint64(wrote))
  319. atomic.AddUint64(&t.rawBytesIn, uint64(wrote))
  320. atomic.AddUint64(&t.packetsRx, 1)
  321. }
  322. }
  323. func (t *TunnelRunner) keepaliveLoop() {
  324. if t.secure != nil {
  325. t.keepaliveSecure()
  326. return
  327. }
  328. // Initiate immediately, then retry quickly until the peer is authenticated.
  329. ticker := time.NewTicker(2 * time.Second)
  330. defer ticker.Stop()
  331. lastSent := time.Time{}
  332. for {
  333. target := t.target()
  334. t.mu.RLock()
  335. connected := !t.lastHandshake.IsZero() && time.Since(t.lastHandshake) < peerTimeout
  336. t.mu.RUnlock()
  337. if target != nil && (!connected || time.Since(lastSent) >= 20*time.Second) {
  338. flags := byte(flagHello)
  339. if connected {
  340. flags = FlagKeepalive
  341. }
  342. if err := t.sendControl(flags, target, zeroSession); err != nil {
  343. t.setError(err)
  344. }
  345. lastSent = time.Now()
  346. }
  347. select {
  348. case <-t.stopChan:
  349. return
  350. case <-ticker.C:
  351. }
  352. }
  353. }
  354. func validIPPacket(b []byte) bool {
  355. if len(b) < 20 {
  356. return false
  357. }
  358. if b[0]>>4 == 4 {
  359. ihl := int(b[0]&15) * 4
  360. return ihl >= 20 && len(b) >= ihl && int(b[2])<<8|int(b[3]) == len(b)
  361. }
  362. if b[0]>>4 == 6 {
  363. return len(b) >= 40 && (int(b[4])<<8|int(b[5]))+40 == len(b)
  364. }
  365. return false
  366. }
  367. func (t *TunnelRunner) GetTelemetry() TunnelInstance {
  368. t.mu.RLock()
  369. inst := t.cfg
  370. if _, ok := t.dev.(*nativeTun); ok {
  371. inst.Backend = "tun"
  372. } else {
  373. inst.Backend = "veth"
  374. }
  375. if t.secure != nil {
  376. inst.Handshakes = t.secure.handshakes.Load()
  377. }
  378. inst.MTU = int(t.effectiveMTU.Load())
  379. inst.ConfiguredMTU = t.configuredMTU
  380. inst.Running = !t.closed
  381. inst.Connected = inst.Running && !t.lastHandshake.IsZero() && time.Since(t.lastHandshake) < peerTimeout
  382. inst.ActivePeerEndpoint = ""
  383. if inst.Connected && t.remoteAddr != nil {
  384. inst.ActivePeerEndpoint = t.remoteAddr.String()
  385. }
  386. inst.LastHandshake = "Never"
  387. if !t.lastHandshake.IsZero() {
  388. inst.LastHandshake = time.Since(t.lastHandshake).Truncate(time.Second).String() + " ago"
  389. }
  390. if t.secure != nil {
  391. session := t.secure.sessions.Load().current
  392. if session == nil || time.Since(session.born) > secureRejectAfter {
  393. inst.Connected = false
  394. inst.ActivePeerEndpoint = ""
  395. }
  396. }
  397. inst.LastError = t.lastError
  398. t.mu.RUnlock()
  399. inst.RxBytes = atomic.LoadUint64(&t.rxBytes)
  400. inst.TxBytes = atomic.LoadUint64(&t.txBytes)
  401. inst.RawBytesIn = atomic.LoadUint64(&t.rawBytesIn)
  402. inst.RawBytesOut = atomic.LoadUint64(&t.rawBytesOut)
  403. inst.WireBytesIn = atomic.LoadUint64(&t.wireBytesIn)
  404. inst.WireBytesOut = atomic.LoadUint64(&t.wireBytesOut)
  405. inst.SavedBytes = atomic.LoadUint64(&t.savedBytes)
  406. inst.PacketsRx = atomic.LoadUint64(&t.packetsRx)
  407. inst.PacketsTx = atomic.LoadUint64(&t.packetsTx)
  408. inst.CompressedPackets = atomic.LoadUint64(&t.compressedPackets)
  409. inst.RawPackets = atomic.LoadUint64(&t.rawPackets)
  410. inst.DroppedPackets = atomic.LoadUint64(&t.droppedPackets)
  411. inst.AuthFailures = atomic.LoadUint64(&t.authFailures)
  412. inst.ReplayDrops = atomic.LoadUint64(&t.replayDrops)
  413. if t.secure != nil {
  414. inst.DropBreakdown = &DropBreakdown{InvalidOutgoing: atomic.LoadUint64(&t.dropInvalidOutgoing), MissingSession: atomic.LoadUint64(&t.dropMissingSession), SendFailure: atomic.LoadUint64(&t.dropSendFailure), InvalidIncoming: atomic.LoadUint64(&t.dropInvalidIncoming), SourcePolicy: atomic.LoadUint64(&t.dropSourcePolicy), InterfaceWrite: atomic.LoadUint64(&t.dropInterfaceWrite)}
  415. }
  416. inst.CompressionRatio = "1.00x (0% saved)"
  417. if inst.RawBytesOut > inst.WireBytesOut && inst.WireBytesOut > 0 {
  418. inst.CompressionRatio = fmt.Sprintf("%.2fx (%.1f%% saved)", float64(inst.RawBytesOut)/float64(inst.WireBytesOut), (1-float64(inst.WireBytesOut)/float64(inst.RawBytesOut))*100)
  419. }
  420. return inst
  421. }
  422. func GenerateSecureKey() (string, error) {
  423. key := make([]byte, 32)
  424. if _, err := rand.Read(key); err != nil {
  425. return "", err
  426. }
  427. return fmt.Sprintf("%x", key), nil
  428. }
  429. func udpAddrsEqual(a, b *net.UDPAddr) bool {
  430. return a != nil && b != nil && a.IP.Equal(b.IP) && a.Port == b.Port && a.Zone == b.Zone
  431. }