66 "net"
77 "strings"
88 "sync"
9+ "time"
910
1011 "k8s.io/klog/v2"
1112
@@ -99,6 +100,7 @@ func (t *tunnelManager) removeTunnels(containerName string) error {
99100// tunnel listens on localIP:localPort and proxies the connection to remoteIP:remotePort
100101type tunnel struct {
101102 listener net.Listener
103+ udpConn * net.UDPConn
102104 localIP string
103105 localPort string
104106 protocol string
@@ -118,35 +120,57 @@ func NewTunnel(localIP, localPort, protocol, remoteIP, remotePort string) *tunne
118120
119121func (t * tunnel ) Start () error {
120122 klog .Infof ("Starting tunnel on %s" , net .JoinHostPort (t .localIP , t .localPort ))
121- ln , err := net .Listen (t .protocol , net .JoinHostPort (t .localIP , t .localPort ))
122- if err != nil {
123- return err
124- }
123+ if t .protocol == "udp" {
124+ localAddrStr := net .JoinHostPort (t .localIP , t .localPort )
125+ udpAddr , err := net .ResolveUDPAddr ("udp" , localAddrStr )
126+ if err != nil {
127+ return err
128+ }
129+ conn , err := net .ListenUDP ("udp" , udpAddr )
130+ t .udpConn = conn
131+ go func () {
132+ for {
133+ err = t .handleUDPConnection (conn )
134+ if err != nil {
135+ klog .Infof ("unexpected error on connection: %v" , err )
136+ }
137+ }
138+ }()
125139
126- t .listener = ln
140+ } else {
141+ ln , err := net .Listen (t .protocol , net .JoinHostPort (t .localIP , t .localPort ))
142+ if err != nil {
143+ return err
144+ }
127145
128- go func () {
129- for {
130- conn , err := ln .Accept ()
131- if err != nil {
132- klog .Infof ("unexpected error listening: %v" , err )
133- return
134- } else {
135- go func () {
136- err := t .handleConnection (conn )
137- if err != nil {
138- klog .Infof ("unexpected error on connection: %v" , err )
139- }
140- }()
146+ t .listener = ln
147+
148+ go func () {
149+ for {
150+ conn , err := ln .Accept ()
151+ if err != nil {
152+ klog .Infof ("unexpected error listening: %v" , err )
153+ return
154+ } else {
155+ go func () {
156+ err := t .handleConnection (conn )
157+ if err != nil {
158+ klog .Infof ("unexpected error on connection: %v" , err )
159+ }
160+ }()
161+ }
141162 }
142- }
143- }()
163+ }()
164+ }
144165 return nil
145166}
146167
147168func (t * tunnel ) Stop () error {
148169 if t .listener != nil {
149- return t .listener .Close ()
170+ _ = t .listener .Close ()
171+ }
172+ if t .udpConn != nil {
173+ _ = t .udpConn .Close ()
150174 }
151175 return nil
152176}
@@ -171,3 +195,42 @@ func (t *tunnel) handleConnection(local net.Conn) error {
171195 wg .Wait ()
172196 return nil
173197}
198+
199+ func (t * tunnel ) handleUDPConnection (conn * net.UDPConn ) error {
200+ buf := make ([]byte , 1500 )
201+ nRead , srcAddr , err := conn .ReadFromUDP (buf )
202+ if err != nil {
203+ return err
204+ }
205+ klog .V (4 ).Infof ("Read %d bytes from %s" , nRead , srcAddr .String ())
206+
207+ klog .V (4 ).Infof ("Connecting to %s" , net .JoinHostPort (t .remoteIP , t .remotePort ))
208+ remoteConn , err := net .Dial (t .protocol , net .JoinHostPort (t .remoteIP , t .remotePort ))
209+ if err != nil {
210+ return fmt .Errorf ("can't connect to server %q: %v" , net .JoinHostPort (t .remoteIP , t .remotePort ), err )
211+ }
212+ defer remoteConn .Close ()
213+
214+ nWrite , err := remoteConn .Write (buf )
215+ if err != nil {
216+ return fmt .Errorf ("fail to write to remote %s: %s" , remoteConn .RemoteAddr (), err )
217+ } else if nWrite < nRead {
218+ klog .V (2 ).Infof ("Buffer underflow %d < %d to remote %s" , nWrite , nRead , remoteConn .RemoteAddr ())
219+ }
220+ klog .V (4 ).Infof ("Wrote %d bytes to to %s" , nWrite , remoteConn .RemoteAddr ().String ())
221+
222+ buf = make ([]byte , 1500 )
223+ err = remoteConn .SetReadDeadline (time .Now ().Add (5 * time .Second )) // Add deadline to ensure it doesn't block forever
224+ if err != nil {
225+ return fmt .Errorf ("can not set read deadline: %v" , err )
226+ }
227+ nRead , err = remoteConn .Read (buf )
228+ if err != nil {
229+ return fmt .Errorf ("fail to read from remote %s: %s" , remoteConn .RemoteAddr (), err )
230+ }
231+ klog .V (4 ).Infof ("Read %d bytes from %s" , nRead , remoteConn .RemoteAddr ().String ())
232+
233+ _ , err = conn .WriteToUDP (buf , srcAddr )
234+
235+ return err
236+ }
0 commit comments