From c6ea37f37e2639ae1be03aff7c79a5962ee70a62 Mon Sep 17 00:00:00 2001 From: djm <> Date: Wed, 21 May 2025 08:41:35 +0000 Subject: add SOCKS4A support to nc(1)'s proxy (-X) mode SOCKS4A is a fairly obscure extension to the olde SOCKS4 protocol that allows passing the destination as a string rather than a literal IPv4 address, which is the only thing that vanilla SOCKS4 supports. The motivation for adding something so niche is to test the SOCKS4A server code in ssh(1)'s dynamic forwarding (-D) support. ok tb@ --- src/usr.bin/nc/nc.1 | 10 ++++++++-- src/usr.bin/nc/netcat.c | 4 +++- src/usr.bin/nc/socks.c | 20 ++++++++++++++++---- 3 files changed, 27 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/usr.bin/nc/nc.1 b/src/usr.bin/nc/nc.1 index 76b6dc018e..e7dc770fca 100644 --- a/src/usr.bin/nc/nc.1 +++ b/src/usr.bin/nc/nc.1 @@ -1,4 +1,4 @@ -.\" $OpenBSD: nc.1,v 1.98 2024/04/01 12:40:18 deraadt Exp $ +.\" $OpenBSD: nc.1,v 1.99 2025/05/21 08:41:35 djm Exp $ .\" .\" Copyright (c) 1996 David Sacerdote .\" All rights reserved. @@ -25,7 +25,7 @@ .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" -.Dd $Mdocdate: April 1 2024 $ +.Dd $Mdocdate: May 21 2025 $ .Dt NC 1 .Os .Sh NAME @@ -338,12 +338,18 @@ when talking to the proxy server. Supported protocols are .Cm 4 (SOCKS v.4), +.Cm 4A +(SOCKS v.4A), .Cm 5 (SOCKS v.5) and .Cm connect (HTTPS proxy). If the protocol is not specified, SOCKS version 5 is used. +Note that the SOCKS v.4 protocol is very limited and can only be used when +the destination host can be resolved to an IPv4 address. +The other protocols pass the destination as a string to be interpreted +by the remote proxy and do not have this limitiation. .It Fl x Ar proxy_address Ns Op : Ns Ar port Connect to .Ar destination diff --git a/src/usr.bin/nc/netcat.c b/src/usr.bin/nc/netcat.c index 67beb10d0a..bf4a7ccf12 100644 --- a/src/usr.bin/nc/netcat.c +++ b/src/usr.bin/nc/netcat.c @@ -1,4 +1,4 @@ -/* $OpenBSD: netcat.c,v 1.230 2025/05/14 08:56:41 tb Exp $ */ +/* $OpenBSD: netcat.c,v 1.231 2025/05/21 08:41:35 djm Exp $ */ /* * Copyright (c) 2001 Eric Jackson * Copyright (c) 2015 Bob Beck. All rights reserved. @@ -190,6 +190,8 @@ main(int argc, char *argv[]) socksv = -1; /* HTTP proxy CONNECT */ else if (strcmp(optarg, "4") == 0) socksv = 4; /* SOCKS v.4 */ + else if (strcasecmp(optarg, "4A") == 0) + socksv = 44; /* SOCKS v.4A */ else if (strcmp(optarg, "5") == 0) socksv = 5; /* SOCKS v.5 */ else diff --git a/src/usr.bin/nc/socks.c b/src/usr.bin/nc/socks.c index 7c7448c9c5..4c5ff90135 100644 --- a/src/usr.bin/nc/socks.c +++ b/src/usr.bin/nc/socks.c @@ -1,4 +1,4 @@ -/* $OpenBSD: socks.c,v 1.31 2022/06/08 20:20:26 djm Exp $ */ +/* $OpenBSD: socks.c,v 1.32 2025/05/21 08:41:35 djm Exp $ */ /* * Copyright (c) 1999 Niklas Hallqvist. All rights reserved. @@ -293,7 +293,7 @@ socks_connect(const char *host, const char *port, default: errx(1, "connection failed, unsupported address type"); } - } else if (socksv == 4) { + } else if (socksv == 4 || socksv == 44) { /* This will exit on lookup failure */ decode_addrport(host, port, (struct sockaddr *)&addr, sizeof(addr), 1, 0); @@ -302,10 +302,22 @@ socks_connect(const char *host, const char *port, buf[0] = SOCKS_V4; buf[1] = SOCKS_CONNECT; /* connect */ memcpy(buf + 2, &in4->sin_port, sizeof in4->sin_port); - memcpy(buf + 4, &in4->sin_addr, sizeof in4->sin_addr); + if (socksv == 4) { + memcpy(buf + 4, &in4->sin_addr, sizeof in4->sin_addr); + } else { + /* SOCKS4A uses addr of 0.0.0.x, and hostname later */ + buf[4] = buf[5] = buf[6] = 0; + buf[7] = 1; + } buf[8] = 0; /* empty username */ wlen = 9; - + if (socksv == 44) { + /* SOCKS4A has nul-terminated hostname after user */ + if (strlcpy(buf + 9, host, + sizeof(buf) - 9) >= sizeof(buf) - 9) + errx(1, "hostname too big"); + wlen = 9 + strlen(host) + 1; + } cnt = atomicio(vwrite, proxyfd, buf, wlen); if (cnt != wlen) err(1, "write failed (%zu/%zu)", cnt, wlen); -- cgit v1.2.3-55-g6feb