AW: AW: Patch for Socks5 support for dynamic portforwaring?

Markus Friedl markus at openbsd.org
Wed Jun 25 21:04:04 EST 2003


On Wed, Jun 25, 2003 at 11:38:01AM +0200, Alex Peuchert wrote:
> you're right... but what do the developers think of that?

there are other nice things you can do with portforwarding, e.g.
this hack.  but i'm not sure whether this code should be
in ssh.

this patch (OpenBSD only for now) allows you to redirect (NAT) TCP
packets to ssh(1) and dynamically forward over ssh.

Index: channels.c
===================================================================
RCS file: /cvs/src/usr.bin/ssh/channels.c,v
retrieving revision 1.191
diff -u -r1.191 channels.c
--- channels.c	24 Jun 2003 08:23:46 -0000	1.191
+++ channels.c	25 Jun 2003 11:00:20 -0000
@@ -41,6 +41,10 @@
 #include "includes.h"
 RCSID("$OpenBSD: channels.c,v 1.191 2003/06/24 08:23:46 markus Exp $");
 
+#include <netinet/in.h>
+#include <net/if.h>
+#include <net/pfvar.h>
+
 #include "ssh.h"
 #include "ssh1.h"
 #include "ssh2.h"
@@ -870,6 +874,73 @@
 	}
 }
 
+static int
+natlookup(int fd, struct sockaddr_in *server)
+{
+	struct pfioc_natlook natlook;
+	struct sockaddr_in from, to;
+	socklen_t slen;
+	int pfd;
+
+	slen = sizeof(from);
+	if (getpeername(fd, (struct sockaddr *)&from, &slen) != 0) {
+		debug("getpeername failed: %s", strerror(errno));
+		return (-1);
+	}
+	slen = sizeof(to);
+	if (getsockname(fd, (struct sockaddr *)&to, &slen) != 0) {
+		debug("getsockname failed: %s", strerror(errno));
+		return (-1);
+	}
+
+	memset(&natlook, 0, sizeof(natlook));
+	natlook.af = AF_INET;
+	natlook.saddr.addr32[0] = from.sin_addr.s_addr;
+	natlook.daddr.addr32[0] = to.sin_addr.s_addr;
+	natlook.proto = IPPROTO_TCP;
+	natlook.sport = from.sin_port;
+	natlook.dport = to.sin_port;
+	natlook.direction = PF_OUT;
+
+	if ((pfd = open("/dev/pf", O_RDWR)) == -1) {
+		debug("open /dev/pf failed: %s", strerror(errno));
+		return (-1);
+	}
+	if (ioctl(pfd, DIOCNATLOOK, &natlook) == -1) {
+		error("pf nat lookup failed: %s", strerror(errno));
+		close(pfd);
+		return (-1);
+	}
+	close(pfd);
+
+	server->sin_port = natlook.rdport;
+	server->sin_addr.s_addr = natlook.rdaddr.addr32[0];
+	server->sin_len = sizeof(struct sockaddr_in);
+	server->sin_family = AF_INET;
+	return (0);
+}
+
+static int
+channel_try_nat(Channel *c)
+{
+	char *host;
+	struct sockaddr_in server;
+
+	memset(&server, 0, sizeof(server));
+
+	if (natlookup(c->rfd, &server) < 0)
+		return (0);
+
+	host = inet_ntoa(server.sin_addr);
+	strlcpy(c->path, host, sizeof(c->path));
+	c->host_port = ntohs(server.sin_port);
+
+	debug("channel %d: nat request: host %s port %u",
+	    c->self, host, c->host_port);
+
+	return (1);
+}
+
 /* try to decode a socks4 header */
 static int
 channel_decode_socks4(Channel *c, fd_set * readset, fd_set * writeset)
@@ -949,6 +1020,10 @@
 
 	have = buffer_len(&c->input);
 	c->delayed = 0;
+
+	if ((ret = channel_try_nat(c)))
+		goto done;
+
 	debug2("channel %d: pre_dynamic: have %d", c->self, have);
 	/* buffer_dump(&c->input); */
 	/* check if the fixed size part of the packet is in buffer. */
@@ -967,6 +1042,8 @@
 		ret = -1;
 		break;
 	}
+
+done:
 	if (ret < 0) {
 		chan_mark_dead(c);
 	} else if (ret == 0) {
@@ -1054,6 +1131,8 @@
 	    "connect from %.200s port %d",
 	    rtype, c->listening_port, c->path, c->host_port,
 	    remote_ipaddr, remote_port);
+
+debug("%s", buf);
 
 	xfree(c->remote_name);
 	c->remote_name = xstrdup(buf);




More information about the openssh-unix-dev mailing list