Skip to content

Commit 327f77b

Browse files
committed
support UDP Port Forwarding
1 parent 348ee5b commit 327f77b

File tree

6 files changed

+406
-16
lines changed

6 files changed

+406
-16
lines changed

tsshd/client.go

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -365,7 +365,7 @@ func (c *SshUdpClient) DialUDP(network, addr string, timeout time.Duration) (Pac
365365
return &sshUdpPacketConn{packetConn: conn, client: c}, nil
366366
}
367367

368-
// Listen requests the remote peer open a listening socket on addr
368+
// Listen requests the remote peer to open a listening socket on addr
369369
func (c *SshUdpClient) Listen(network, addr string) (net.Listener, error) {
370370
stream, err := c.newStream("listen")
371371
if err != nil {
@@ -387,6 +387,28 @@ func (c *SshUdpClient) Listen(network, addr string) (net.Listener, error) {
387387
return &sshUdpListener{client: c, stream: stream}, nil
388388
}
389389

390+
// ListenUDP requests the remote peer to open a UDP listening endpoint on addr
391+
func (c *SshUdpClient) ListenUDP(network, addr string) (PacketListener, error) {
392+
stream, err := c.newStream("listen-udp")
393+
if err != nil {
394+
return nil, err
395+
}
396+
msg := listenUdpMessage{
397+
Net: network,
398+
Addr: addr,
399+
}
400+
if err := sendMessage(stream, &msg); err != nil {
401+
_ = stream.Close()
402+
return nil, fmt.Errorf("send listen udp message failed: %w", err)
403+
}
404+
if err := recvError(stream); err != nil {
405+
_ = stream.Close()
406+
return nil, err
407+
}
408+
c.exitWG.Add(1)
409+
return &sshUdpPacketListener{client: c, stream: stream}, nil
410+
}
411+
390412
// HandleChannelOpen returns a channel on which NewChannel requests
391413
func (c *SshUdpClient) HandleChannelOpen(channelType string) <-chan ssh.NewChannel {
392414
c.channelMutex.Lock()
@@ -1249,3 +1271,43 @@ func (c *sshUdpPacketConn) Close() error {
12491271
c.client.exitWG.Done()
12501272
return err
12511273
}
1274+
1275+
type sshUdpPacketListener struct {
1276+
client *SshUdpClient
1277+
stream Stream
1278+
closed atomic.Bool
1279+
}
1280+
1281+
func (l *sshUdpPacketListener) AcceptUDP() (PacketConn, error) {
1282+
var msg acceptUdpMessage
1283+
if err := recvMessage(l.stream, &msg); err != nil {
1284+
return nil, fmt.Errorf("recv accept udp message failed: %w", err)
1285+
}
1286+
stream, err := l.client.newStream("accept-udp")
1287+
if err != nil {
1288+
return nil, err
1289+
}
1290+
1291+
conn := newPacketConn(stream, msg.ID, l.client.protoClient.getUdpForwarder(), l.client.networkProxy.serverChecker)
1292+
1293+
if err := sendMessage(stream, &msg); err != nil {
1294+
_ = stream.Close()
1295+
return nil, fmt.Errorf("send accept udp message failed: %w", err)
1296+
}
1297+
if err := recvError(stream); err != nil {
1298+
_ = stream.Close()
1299+
return nil, err
1300+
}
1301+
1302+
l.client.exitWG.Add(1)
1303+
return &sshUdpPacketConn{packetConn: conn, client: l.client}, nil
1304+
}
1305+
1306+
func (l *sshUdpPacketListener) Close() error {
1307+
if !l.closed.CompareAndSwap(false, true) {
1308+
return nil
1309+
}
1310+
err := l.stream.Close()
1311+
l.client.exitWG.Done()
1312+
return err
1313+
}

0 commit comments

Comments
 (0)