secure_io.go 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  1. package aerotun
  2. import (
  3. "encoding/binary"
  4. "errors"
  5. "fmt"
  6. "net"
  7. "net/netip"
  8. "sync/atomic"
  9. "syscall"
  10. "time"
  11. "github.com/pierrec/lz4/v4"
  12. "golang.org/x/net/ipv4"
  13. "golang.org/x/net/ipv6"
  14. )
  15. const secureBatchSize = 16
  16. type batchSocket interface {
  17. ReadBatch([]ipv4.Message, int) (int, error)
  18. WriteBatch([]ipv4.Message, int) (int, error)
  19. }
  20. func newBatchSocket(c *net.UDPConn) batchSocket {
  21. if c.LocalAddr().(*net.UDPAddr).IP.To4() != nil {
  22. return ipv4.NewPacketConn(c)
  23. }
  24. return ipv6.NewPacketConn(c)
  25. }
  26. type securePacket struct {
  27. buf []byte
  28. n, wire int
  29. compressed bool
  30. }
  31. func (t *TunnelRunner) txLoopSecure() {
  32. size := t.cfg.MTU + secureHeaderSize + 16
  33. pool := make(chan *securePacket, secureBatchSize*2)
  34. queue := make(chan *securePacket, secureBatchSize)
  35. for range cap(pool) {
  36. pool <- &securePacket{buf: make([]byte, size)}
  37. }
  38. done := make(chan struct{})
  39. go func() {
  40. defer close(done)
  41. defer close(queue)
  42. for {
  43. var p *securePacket
  44. select {
  45. case <-t.stopChan:
  46. return
  47. case p = <-pool:
  48. }
  49. n, err := t.dev.Read(p.buf[secureHeaderSize : secureHeaderSize+t.cfg.MTU])
  50. if err != nil {
  51. select {
  52. case <-t.stopChan:
  53. return
  54. default:
  55. }
  56. t.setError(fmt.Errorf("secure interface read: %w", err))
  57. pool <- p
  58. time.Sleep(10 * time.Millisecond)
  59. continue
  60. }
  61. if n == 0 || n > int(t.effectiveMTU.Load()) || !validIPPacket(p.buf[secureHeaderSize:secureHeaderSize+n]) {
  62. atomic.AddUint64(&t.droppedPackets, 1)
  63. pool <- p
  64. continue
  65. }
  66. p.n = n
  67. select {
  68. case <-t.stopChan:
  69. return
  70. case queue <- p:
  71. }
  72. }
  73. }()
  74. defer func() { <-done }()
  75. conn := newBatchSocket(t.udpConn)
  76. messages := make([]ipv4.Message, secureBatchSize)
  77. var buffers [secureBatchSize][1][]byte
  78. for i := range messages {
  79. messages[i].Buffers = buffers[i][:]
  80. }
  81. var packets [secureBatchSize]*securePacket
  82. var nonce [24]byte
  83. var comp []byte
  84. if t.cfg.Compression {
  85. comp = make([]byte, lz4.CompressBlockBound(t.cfg.MTU))
  86. }
  87. for {
  88. var first *securePacket
  89. select {
  90. case <-t.stopChan:
  91. return
  92. case p, ok := <-queue:
  93. if !ok {
  94. return
  95. }
  96. first = p
  97. }
  98. count := 1
  99. packets[0] = first
  100. drain:
  101. for count < secureBatchSize {
  102. select {
  103. case p, ok := <-queue:
  104. if !ok {
  105. break drain
  106. }
  107. packets[count] = p
  108. count++
  109. default:
  110. break drain
  111. }
  112. }
  113. target := t.target()
  114. ready := 0
  115. for i := 0; i < count; i++ {
  116. p := packets[i]
  117. payload := p.buf[secureHeaderSize : secureHeaderSize+p.n]
  118. flags := byte(0)
  119. p.compressed = false
  120. p.wire = p.n
  121. if target != nil && t.secure.compressionEnabled() && len(comp) > 0 && p.n > 40 {
  122. if n, err := lz4.CompressBlock(payload, comp, nil); err == nil && n > 0 && n < p.n-16 {
  123. payload = comp[:n]
  124. flags = FlagCompressedLZ4
  125. p.compressed = true
  126. p.wire = n
  127. }
  128. }
  129. if target == nil {
  130. atomic.AddUint64(&t.droppedPackets, 1)
  131. pool <- p
  132. continue
  133. }
  134. out, err := t.secure.sealInto(p.buf[:0], &nonce, flags, payload)
  135. if err != nil {
  136. atomic.AddUint64(&t.droppedPackets, 1)
  137. pool <- p
  138. continue
  139. }
  140. packets[ready] = p
  141. messages[ready].Buffers[0] = out
  142. messages[ready].Addr = target
  143. ready++
  144. }
  145. sent := 0
  146. for sent < ready {
  147. n, err := conn.WriteBatch(messages[sent:ready], 0)
  148. for j := sent; j < sent+n; j++ {
  149. p := packets[j]
  150. atomic.AddUint64(&t.txBytes, uint64(p.n))
  151. atomic.AddUint64(&t.rawBytesOut, uint64(p.n))
  152. atomic.AddUint64(&t.packetsTx, 1)
  153. atomic.AddUint64(&t.wireBytesOut, uint64(len(messages[j].Buffers[0])))
  154. if p.compressed {
  155. atomic.AddUint64(&t.compressedPackets, 1)
  156. atomic.AddUint64(&t.savedBytes, uint64(p.n-p.wire))
  157. } else {
  158. atomic.AddUint64(&t.rawPackets, 1)
  159. }
  160. }
  161. sent += n
  162. if err != nil || n == 0 {
  163. if err != nil {
  164. t.setError(err)
  165. }
  166. atomic.AddUint64(&t.droppedPackets, uint64(ready-sent))
  167. break
  168. }
  169. }
  170. for i := 0; i < ready; i++ {
  171. pool <- packets[i]
  172. }
  173. }
  174. }
  175. func (t *TunnelRunner) allowedSource(b []byte) bool {
  176. var src netip.Addr
  177. if b[0]>>4 == 4 {
  178. var ip [4]byte
  179. copy(ip[:], b[12:16])
  180. src = netip.AddrFrom4(ip)
  181. } else {
  182. var ip [16]byte
  183. copy(ip[:], b[8:24])
  184. src = netip.AddrFrom16(ip)
  185. }
  186. for _, prefix := range t.allowed {
  187. if prefix.Contains(src) {
  188. return true
  189. }
  190. }
  191. return false
  192. }
  193. func (t *TunnelRunner) rxLoopSecure() {
  194. conn := newBatchSocket(t.udpConn)
  195. size := max(t.cfg.MTU+secureHeaderSize+16, handshakeMaxSize)
  196. messages := make([]ipv4.Message, secureBatchSize)
  197. buffers := make([][]byte, secureBatchSize)
  198. var vectors [secureBatchSize][1][]byte
  199. for i := range messages {
  200. buffers[i] = make([]byte, size)
  201. vectors[i][0] = buffers[i]
  202. messages[i].Buffers = vectors[i][:]
  203. }
  204. plain := make([]byte, t.cfg.MTU)
  205. var decomp []byte
  206. if t.cfg.Compression {
  207. decomp = make([]byte, t.cfg.MTU)
  208. }
  209. var nonce [24]byte
  210. for {
  211. n, err := conn.ReadBatch(messages, 0)
  212. if err != nil {
  213. select {
  214. case <-t.stopChan:
  215. return
  216. default:
  217. }
  218. t.setError(err)
  219. continue
  220. }
  221. for i := 0; i < n; i++ {
  222. m := &messages[i]
  223. src, ok := m.Addr.(*net.UDPAddr)
  224. if !ok || m.Flags&syscall.MSG_TRUNC != 0 || m.N < secureHeaderSize+16 {
  225. atomic.AddUint64(&t.droppedPackets, 1)
  226. continue
  227. }
  228. if t.cfg.Mode == "client" && !udpAddrsEqual(t.target(), src) {
  229. continue
  230. }
  231. b := m.Buffers[0][:m.N]
  232. if b[2] != 3 {
  233. atomic.AddUint64(&t.authFailures, 1)
  234. continue
  235. }
  236. if b[3] == secureInit || b[3] == secureResponse || b[3] == secureCookie {
  237. response, peerMTU, err := t.secure.handleHandshake(b, int(t.effectiveMTU.Load()), src.AddrPort())
  238. if err != nil {
  239. if !errors.Is(err, errHandshakeRate) {
  240. atomic.AddUint64(&t.authFailures, 1)
  241. }
  242. continue
  243. }
  244. atomic.AddUint64(&t.wireBytesIn, uint64(m.N))
  245. if response != nil {
  246. if n, err := t.udpConn.WriteToUDP(response, src); err == nil {
  247. atomic.AddUint64(&t.wireBytesOut, uint64(n))
  248. } else {
  249. t.setError(err)
  250. }
  251. }
  252. if peerMTU > 0 {
  253. if err := t.adjustMTU(src.IP, peerMTU); err != nil {
  254. t.setError(err)
  255. continue
  256. }
  257. t.markSecurePeer(src)
  258. if err := t.sendControl(FlagKeepalive, src, zeroSession); err != nil {
  259. t.setError(err)
  260. }
  261. }
  262. continue
  263. }
  264. payload, flags, peerMTU, err := t.secure.openInto(plain, &nonce, b)
  265. if err != nil {
  266. if errors.Is(err, errReplay) {
  267. atomic.AddUint64(&t.replayDrops, 1)
  268. } else {
  269. atomic.AddUint64(&t.authFailures, 1)
  270. }
  271. continue
  272. }
  273. atomic.AddUint64(&t.wireBytesIn, uint64(m.N))
  274. oldMTU := t.effectiveMTU.Load()
  275. if flags == FlagKeepalive {
  276. peerMTU = int(binary.BigEndian.Uint16(payload))
  277. }
  278. if peerMTU > 0 {
  279. if err := t.adjustMTU(src.IP, peerMTU); err != nil {
  280. t.setError(err)
  281. continue
  282. }
  283. }
  284. t.markSecurePeer(src)
  285. if flags == FlagKeepalive {
  286. if t.effectiveMTU.Load() < oldMTU {
  287. if err := t.sendControl(FlagKeepalive, src, zeroSession); err != nil {
  288. t.setError(err)
  289. }
  290. }
  291. continue
  292. }
  293. if flags == FlagCompressedLZ4 {
  294. if len(decomp) == 0 {
  295. atomic.AddUint64(&t.droppedPackets, 1)
  296. continue
  297. }
  298. size, err := lz4.UncompressBlock(payload, decomp[:int(t.effectiveMTU.Load())])
  299. if err != nil || size == 0 {
  300. atomic.AddUint64(&t.droppedPackets, 1)
  301. continue
  302. }
  303. payload = decomp[:size]
  304. }
  305. if len(payload) > int(t.effectiveMTU.Load()) || !validIPPacket(payload) || !t.allowedSource(payload) {
  306. atomic.AddUint64(&t.droppedPackets, 1)
  307. continue
  308. }
  309. wrote, err := t.dev.Write(payload)
  310. if err != nil || wrote != len(payload) {
  311. atomic.AddUint64(&t.droppedPackets, 1)
  312. if err != nil {
  313. t.setError(err)
  314. }
  315. continue
  316. }
  317. atomic.AddUint64(&t.rxBytes, uint64(wrote))
  318. atomic.AddUint64(&t.rawBytesIn, uint64(wrote))
  319. atomic.AddUint64(&t.packetsRx, 1)
  320. }
  321. }
  322. }
  323. func (t *TunnelRunner) markSecurePeer(src *net.UDPAddr) {
  324. t.mu.Lock()
  325. if !udpAddrsEqual(t.remoteAddr, src) {
  326. t.remoteAddr = src
  327. }
  328. t.lastHandshake = time.Now()
  329. t.mu.Unlock()
  330. }
  331. func (t *TunnelRunner) keepaliveSecure() {
  332. ticker := time.NewTicker(time.Second)
  333. defer ticker.Stop()
  334. lastSent := time.Time{}
  335. for {
  336. t.secure.expire()
  337. target := t.target()
  338. t.mu.RLock()
  339. connected := !t.lastHandshake.IsZero() && time.Since(t.lastHandshake) < peerTimeout
  340. t.mu.RUnlock()
  341. if target != nil {
  342. b, err := t.secure.initiation(int(t.effectiveMTU.Load()), !connected)
  343. if err != nil {
  344. t.setError(err)
  345. } else if b != nil {
  346. if n, err := t.udpConn.WriteToUDP(b, target); err == nil {
  347. atomic.AddUint64(&t.wireBytesOut, uint64(n))
  348. } else {
  349. t.setError(err)
  350. }
  351. }
  352. if connected && time.Since(lastSent) >= 20*time.Second {
  353. if err := t.sendControl(FlagKeepalive, target, zeroSession); err != nil {
  354. t.setError(err)
  355. }
  356. lastSent = time.Now()
  357. }
  358. }
  359. select {
  360. case <-t.stopChan:
  361. return
  362. case <-ticker.C:
  363. }
  364. }
  365. }