Combining Transparent Proxying with SSH Port Forwarding
Markus Friedl
markus at openbsd.org
Fri Sep 12 19:05:15 EST 2003
On Fri, Sep 12, 2003 at 12:04:33AM -0500, Greg Houlette wrote:
> The Dynamic Forwarding that is currently in OpenSSH (-D option)
> which uses the SOCKS protocol, still requires an application-level
> 'socksifier' to provide transparency on the client side, but lacks
> other features of a traditional transparent proxy (such as NAT)?
using the attached patch you can redirect
traffic to the -D port. using OpenBSD's NAT
this wold look like:
rdr on eth0 inet proto tcp from any to 10/8 -> 127.0.0.1 port 8080
> I haven't seen or used any of the patches that Damien mentioned, and
see below.
> [...]
> The idea of a standalone transparent NAT -> SOCKS gateway daemon
> is something that I haven't seen, let alone with the other features
> that I mentioned in my post. That does seem like a good starting
> point though. And I like the independent utility aspect of it.
>
> I wish Markus would elaborate about what he's using?
a process listens to a port, the kernel NAT rules redirect traffic
to this port, process does NAT lookup and connects to ssh's -D port
after converting the NAT state to a SOCKS4 request.
Index: channels.c
===================================================================
RCS file: /cvs/src/usr.bin/ssh/channels.c,v
retrieving revision 1.194
diff -u -r1.194 channels.c
--- channels.c 29 Aug 2003 10:04:36 -0000 1.194
+++ channels.c 11 Sep 2003 15:59:59 -0000
@@ -41,6 +41,10 @@
#include "includes.h"
RCSID("$OpenBSD: channels.c,v 1.194 2003/08/29 10:04:36 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)
@@ -1060,6 +1131,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. */
@@ -1081,6 +1156,8 @@
ret = -1;
break;
}
+
+done:
if (ret < 0) {
chan_mark_dead(c);
} else if (ret == 0) {
@@ -1168,6 +1245,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