Skip to content

Commit 13fff36

Browse files
committed
Added support domain name address type for SOCKS5.
Fixes issue #98.
1 parent 5a1e469 commit 13fff36

File tree

1 file changed

+72
-60
lines changed

1 file changed

+72
-60
lines changed

src/Renci.SshNet/ForwardedPortDynamic.NET.cs

+72-60
Original file line numberDiff line numberDiff line change
@@ -435,106 +435,118 @@ private bool HandleSocks5(Socket socket, IChannelDirectTcpip channel, TimeSpan t
435435
return false;
436436
}
437437

438-
IPAddress ipAddress;
439-
byte[] addressBuffer;
438+
var host = GetSocks5Host(addressType, socket, timeout);
439+
if (host == null)
440+
{
441+
// SOCKS client closed connection
442+
return false;
443+
}
444+
445+
var portBuffer = new byte[2];
446+
if (SocketAbstraction.Read(socket, portBuffer, 0, portBuffer.Length, timeout) == 0)
447+
{
448+
// SOCKS client closed connection
449+
return false;
450+
}
451+
452+
var port = (uint)(portBuffer[0] * 256 + portBuffer[1]);
453+
454+
RaiseRequestReceived(host, port);
455+
456+
channel.Open(host, port, this, socket);
457+
458+
var socksReply = CreateSocks5Reply(channel.IsOpen);
459+
460+
SocketAbstraction.Send(socket, socksReply, 0, socksReply.Length);
461+
462+
return true;
463+
}
464+
465+
private static string GetSocks5Host(int addressType, Socket socket, TimeSpan timeout)
466+
{
440467
switch (addressType)
441468
{
442-
case 0x01:
469+
case 0x01: // IPv4
443470
{
444-
addressBuffer = new byte[4];
471+
var addressBuffer = new byte[4];
445472
if (SocketAbstraction.Read(socket, addressBuffer, 0, 4, timeout) == 0)
446473
{
447474
// SOCKS client closed connection
448-
return false;
475+
return null;
449476
}
450477

451-
ipAddress = new IPAddress(addressBuffer);
478+
var ipv4 = new IPAddress(addressBuffer);
479+
return ipv4.ToString();
452480
}
453-
break;
454-
case 0x03:
481+
case 0x03: // Domain name
455482
{
456483
var length = SocketAbstraction.ReadByte(socket, timeout);
457484
if (length == -1)
458485
{
459486
// SOCKS client closed connection
460-
return false;
487+
return null;
461488
}
462-
addressBuffer = new byte[length];
489+
var addressBuffer = new byte[length];
463490
if (SocketAbstraction.Read(socket, addressBuffer, 0, addressBuffer.Length, timeout) == 0)
464491
{
465492
// SOCKS client closed connection
466-
return false;
493+
return null;
467494
}
468495

469-
ipAddress = IPAddress.Parse(SshData.Ascii.GetString(addressBuffer, 0, addressBuffer.Length));
470-
471-
//var hostName = new Common.ASCIIEncoding().GetString(addressBuffer);
472-
473-
//ipAddress = Dns.GetHostEntry(hostName).AddressList[0];
496+
var hostName = SshData.Ascii.GetString(addressBuffer);
497+
return hostName;
474498
}
475-
break;
476-
case 0x04:
499+
case 0x04: // IPv6
477500
{
478-
addressBuffer = new byte[16];
501+
var addressBuffer = new byte[16];
479502
if (SocketAbstraction.Read(socket, addressBuffer, 0, 16, timeout) == 0)
480503
{
481504
// SOCKS client closed connection
482-
return false;
505+
return null;
483506
}
484507

485-
ipAddress = new IPAddress(addressBuffer);
508+
var ipv6 = new IPAddress(addressBuffer);
509+
return ipv6.ToString();
486510
}
487-
break;
488511
default:
489512
throw new ProxyException(string.Format("SOCKS5: Address type '{0}' is not supported.", addressType));
490513
}
514+
}
491515

492-
var portBuffer = new byte[2];
493-
if (SocketAbstraction.Read(socket, portBuffer, 0, portBuffer.Length, timeout) == 0)
494-
{
495-
// SOCKS client closed connection
496-
return false;
497-
}
498-
499-
var port = (uint)(portBuffer[0] * 256 + portBuffer[1]);
500-
var host = ipAddress.ToString();
501-
502-
RaiseRequestReceived(host, port);
503-
504-
channel.Open(host, port, this, socket);
505-
506-
SocketAbstraction.SendByte(socket, 0x05);
507-
508-
if (channel.IsOpen)
509-
{
510-
SocketAbstraction.SendByte(socket, 0x00);
516+
private static byte[] CreateSocks5Reply(bool channelOpen)
517+
{
518+
var socksReply = new byte[
519+
// SOCKS version
520+
1 +
521+
// Reply field
522+
1 +
523+
// Reserved; fixed: 0x00
524+
1 +
525+
// Address type; fixed: 0x01
526+
1 +
527+
// IPv4 server bound address; fixed: {0x00, 0x00, 0x00, 0x00}
528+
4 +
529+
// server bound port; fixed: {0x00, 0x00}
530+
2];
531+
532+
socksReply[0] = 0x05;
533+
534+
if (channelOpen)
535+
{
536+
socksReply[1] = 0x00; // succeeded
511537
}
512538
else
513539
{
514-
SocketAbstraction.SendByte(socket, 0x01);
540+
socksReply[1] = 0x01; // general SOCKS server failure
515541
}
516542

517543
// reserved
518-
SocketAbstraction.SendByte(socket, 0x00);
519-
520-
if (ipAddress.AddressFamily == AddressFamily.InterNetwork)
521-
{
522-
SocketAbstraction.SendByte(socket, 0x01);
523-
}
524-
else if (ipAddress.AddressFamily == AddressFamily.InterNetworkV6)
525-
{
526-
SocketAbstraction.SendByte(socket, 0x04);
527-
}
528-
else
529-
{
530-
throw new NotSupportedException("Not supported address family.");
531-
}
544+
socksReply[2] = 0x00;
532545

533-
var addressBytes = ipAddress.GetAddressBytes();
534-
SocketAbstraction.Send(socket, addressBytes, 0, addressBytes.Length);
535-
SocketAbstraction.Send(socket, portBuffer, 0, portBuffer.Length);
546+
// IPv4 address type
547+
socksReply[3] = 0x01;
536548

537-
return true;
549+
return socksReply;
538550
}
539551

540552
/// <summary>

0 commit comments

Comments
 (0)