summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordjm <>2025-05-21 08:41:35 +0000
committerdjm <>2025-05-21 08:41:35 +0000
commitc6ea37f37e2639ae1be03aff7c79a5962ee70a62 (patch)
treefd82dbfdcc3f7656a8be12d00e46cfac88c898d3 /src
parent80cafa36f69e0e544fce4f1ced15c277adaba45c (diff)
downloadopenbsd-c6ea37f37e2639ae1be03aff7c79a5962ee70a62.tar.gz
openbsd-c6ea37f37e2639ae1be03aff7c79a5962ee70a62.tar.bz2
openbsd-c6ea37f37e2639ae1be03aff7c79a5962ee70a62.zip
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@
Diffstat (limited to 'src')
-rw-r--r--src/usr.bin/nc/nc.110
-rw-r--r--src/usr.bin/nc/netcat.c4
-rw-r--r--src/usr.bin/nc/socks.c20
3 files changed, 27 insertions, 7 deletions
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 @@
1.\" $OpenBSD: nc.1,v 1.98 2024/04/01 12:40:18 deraadt Exp $ 1.\" $OpenBSD: nc.1,v 1.99 2025/05/21 08:41:35 djm Exp $
2.\" 2.\"
3.\" Copyright (c) 1996 David Sacerdote 3.\" Copyright (c) 1996 David Sacerdote
4.\" All rights reserved. 4.\" All rights reserved.
@@ -25,7 +25,7 @@
25.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27.\" 27.\"
28.Dd $Mdocdate: April 1 2024 $ 28.Dd $Mdocdate: May 21 2025 $
29.Dt NC 1 29.Dt NC 1
30.Os 30.Os
31.Sh NAME 31.Sh NAME
@@ -338,12 +338,18 @@ when talking to the proxy server.
338Supported protocols are 338Supported protocols are
339.Cm 4 339.Cm 4
340(SOCKS v.4), 340(SOCKS v.4),
341.Cm 4A
342(SOCKS v.4A),
341.Cm 5 343.Cm 5
342(SOCKS v.5) 344(SOCKS v.5)
343and 345and
344.Cm connect 346.Cm connect
345(HTTPS proxy). 347(HTTPS proxy).
346If the protocol is not specified, SOCKS version 5 is used. 348If the protocol is not specified, SOCKS version 5 is used.
349Note that the SOCKS v.4 protocol is very limited and can only be used when
350the destination host can be resolved to an IPv4 address.
351The other protocols pass the destination as a string to be interpreted
352by the remote proxy and do not have this limitiation.
347.It Fl x Ar proxy_address Ns Op : Ns Ar port 353.It Fl x Ar proxy_address Ns Op : Ns Ar port
348Connect to 354Connect to
349.Ar destination 355.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 @@
1/* $OpenBSD: netcat.c,v 1.230 2025/05/14 08:56:41 tb Exp $ */ 1/* $OpenBSD: netcat.c,v 1.231 2025/05/21 08:41:35 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2001 Eric Jackson <ericj@monkey.org> 3 * Copyright (c) 2001 Eric Jackson <ericj@monkey.org>
4 * Copyright (c) 2015 Bob Beck. All rights reserved. 4 * Copyright (c) 2015 Bob Beck. All rights reserved.
@@ -190,6 +190,8 @@ main(int argc, char *argv[])
190 socksv = -1; /* HTTP proxy CONNECT */ 190 socksv = -1; /* HTTP proxy CONNECT */
191 else if (strcmp(optarg, "4") == 0) 191 else if (strcmp(optarg, "4") == 0)
192 socksv = 4; /* SOCKS v.4 */ 192 socksv = 4; /* SOCKS v.4 */
193 else if (strcasecmp(optarg, "4A") == 0)
194 socksv = 44; /* SOCKS v.4A */
193 else if (strcmp(optarg, "5") == 0) 195 else if (strcmp(optarg, "5") == 0)
194 socksv = 5; /* SOCKS v.5 */ 196 socksv = 5; /* SOCKS v.5 */
195 else 197 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 @@
1/* $OpenBSD: socks.c,v 1.31 2022/06/08 20:20:26 djm Exp $ */ 1/* $OpenBSD: socks.c,v 1.32 2025/05/21 08:41:35 djm Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1999 Niklas Hallqvist. All rights reserved. 4 * Copyright (c) 1999 Niklas Hallqvist. All rights reserved.
@@ -293,7 +293,7 @@ socks_connect(const char *host, const char *port,
293 default: 293 default:
294 errx(1, "connection failed, unsupported address type"); 294 errx(1, "connection failed, unsupported address type");
295 } 295 }
296 } else if (socksv == 4) { 296 } else if (socksv == 4 || socksv == 44) {
297 /* This will exit on lookup failure */ 297 /* This will exit on lookup failure */
298 decode_addrport(host, port, (struct sockaddr *)&addr, 298 decode_addrport(host, port, (struct sockaddr *)&addr,
299 sizeof(addr), 1, 0); 299 sizeof(addr), 1, 0);
@@ -302,10 +302,22 @@ socks_connect(const char *host, const char *port,
302 buf[0] = SOCKS_V4; 302 buf[0] = SOCKS_V4;
303 buf[1] = SOCKS_CONNECT; /* connect */ 303 buf[1] = SOCKS_CONNECT; /* connect */
304 memcpy(buf + 2, &in4->sin_port, sizeof in4->sin_port); 304 memcpy(buf + 2, &in4->sin_port, sizeof in4->sin_port);
305 memcpy(buf + 4, &in4->sin_addr, sizeof in4->sin_addr); 305 if (socksv == 4) {
306 memcpy(buf + 4, &in4->sin_addr, sizeof in4->sin_addr);
307 } else {
308 /* SOCKS4A uses addr of 0.0.0.x, and hostname later */
309 buf[4] = buf[5] = buf[6] = 0;
310 buf[7] = 1;
311 }
306 buf[8] = 0; /* empty username */ 312 buf[8] = 0; /* empty username */
307 wlen = 9; 313 wlen = 9;
308 314 if (socksv == 44) {
315 /* SOCKS4A has nul-terminated hostname after user */
316 if (strlcpy(buf + 9, host,
317 sizeof(buf) - 9) >= sizeof(buf) - 9)
318 errx(1, "hostname too big");
319 wlen = 9 + strlen(host) + 1;
320 }
309 cnt = atomicio(vwrite, proxyfd, buf, wlen); 321 cnt = atomicio(vwrite, proxyfd, buf, wlen);
310 if (cnt != wlen) 322 if (cnt != wlen)
311 err(1, "write failed (%zu/%zu)", cnt, wlen); 323 err(1, "write failed (%zu/%zu)", cnt, wlen);