11package tun
22
33import (
4+ "context"
45 "net/netip"
56 "sync"
7+ "time"
68)
79
810type TCPNat struct {
@@ -16,20 +18,54 @@ type TCPNat struct {
1618type TCPSession struct {
1719 Source netip.AddrPort
1820 Destination netip.AddrPort
21+ LastActive time.Time
1922}
2023
21- func NewNat () * TCPNat {
22- return & TCPNat {
24+ func NewNat (ctx context. Context , timeout time. Duration ) * TCPNat {
25+ natMap := & TCPNat {
2326 portIndex : 10000 ,
2427 addrMap : make (map [netip.AddrPort ]uint16 ),
2528 portMap : make (map [uint16 ]* TCPSession ),
2629 }
30+ go natMap .loopCheckTimeout (ctx , timeout )
31+ return natMap
32+ }
33+
34+ func (n * TCPNat ) loopCheckTimeout (ctx context.Context , timeout time.Duration ) {
35+ ticker := time .NewTicker (timeout )
36+ defer ticker .Stop ()
37+ for {
38+ select {
39+ case <- ticker .C :
40+ n .checkTimeout (timeout )
41+ case <- ctx .Done ():
42+ return
43+ }
44+ }
45+ }
46+
47+ func (n * TCPNat ) checkTimeout (timeout time.Duration ) {
48+ now := time .Now ()
49+ n .portAccess .Lock ()
50+ defer n .portAccess .Unlock ()
51+ n .addrAccess .Lock ()
52+ defer n .addrAccess .Unlock ()
53+ for natPort , session := range n .portMap {
54+ if now .Sub (session .LastActive ) > timeout {
55+ delete (n .addrMap , session .Source )
56+ delete (n .portMap , natPort )
57+ }
58+ }
2759}
2860
2961func (n * TCPNat ) LookupBack (port uint16 ) * TCPSession {
3062 n .portAccess .RLock ()
31- defer n .portAccess .RUnlock ()
32- return n .portMap [port ]
63+ session := n .portMap [port ]
64+ n .portAccess .RUnlock ()
65+ if session != nil {
66+ session .LastActive = time .Now ()
67+ }
68+ return session
3369}
3470
3571func (n * TCPNat ) Lookup (source netip.AddrPort , destination netip.AddrPort ) uint16 {
@@ -53,16 +89,8 @@ func (n *TCPNat) Lookup(source netip.AddrPort, destination netip.AddrPort) uint1
5389 n .portMap [nextPort ] = & TCPSession {
5490 Source : source ,
5591 Destination : destination ,
92+ LastActive : time .Now (),
5693 }
5794 n .portAccess .Unlock ()
5895 return nextPort
5996}
60-
61- func (n * TCPNat ) Revoke (natPort uint16 , session * TCPSession ) {
62- n .addrAccess .Lock ()
63- delete (n .addrMap , session .Source )
64- n .addrAccess .Unlock ()
65- n .portAccess .Lock ()
66- delete (n .portMap , natPort )
67- n .portAccess .Unlock ()
68- }
0 commit comments