[prev in list] [next in list] [prev in thread] [next in thread] 

List:       secure-shell
Subject:    Transparent proxy through firewalls using ssh
From:       Dominique Unruh <dominique () unruh ! de>
Date:       1999-02-16 10:48:25
[Download RAW message or body]

This is a patch for ssh (tested with version 1.2.21, may need minor
modifications for other versions) to be able to have socks-like
transparent forwarding through ssh.

Advantages:

- You do only need a normal sshd on the other side (no socksd or alike).

- You have encryption to the host on the other side (no to the target!)

- You dont have to change your software (like with socks)

- You can use this on a local router to route a whole local network
(untested under heavier load)


Disadvantages:

- You need linux on the client machine

- You cant forward udp




If you add this patch to a ssh distribution (which I would appreciate),
please put my name somewhere in it and send me a little note.

If you have replies for me, please contact me directly, I am not in the
ssh mailing list.


DniQ.
["ssh-dynamic.dif" (text/plain)]

Building a transparent proxy through firewalls using ssh
========================================================

Prerequisites:
Linux on your machine
A host which is not firewalled on which you have an ssh-able account
This patch


This patch is needed to have dynamic port forwarding with ssh (probably only under \
Linux).

How to use:

1. Create a transparent firewall rule for all connections to be routed
through ssh on local port <port>

2. Run ssh with -L <port>:DYN:0.

3. Make a connect to any address covered by the above firewalling
rule. The connection will be routed through ssh and connect from the
remote host to the target

How it works:

If the target host name is "DYN", ssh will check via getsockname which host/port the \
connection is for. At least under Linux, Kernel 2.0.35 this will be the original \
target, not the local port which ssh is listening on.


Hint:

If you want to forward connections originating from the local host,
you wont be able to simple make a firewalling rule like -I -D <dest>
-P tcp -r <port>, because this will only route incoming connections.
The only workaround I found was to route the connection to be
forwarded through the loopback device and then apply the firewalling
rule, because connections through lo will be handled as outgoing and
incoming connections at the same time (You'll have to take a larger netmask for lo \
than).


Comment:

This was tested on my computer for several months.
I am behind a firewall in our universitary network and running Linux 2.0.35.
There is no change on the sshd needed.


Sample:

# if forwarding shall be for routed connections only:

# Reroute connections to be forwarded
ipfwadm -I -a accept -D <what to forward> -r <someport>

# Tell ssh to forward
ssh <normal connection information> -L <someport>:DYN:0

# end




# or, if locally originating connections should be forwarded, too

# To be able to route everything through it
ifconfig lo netmask 0.0.0.0

# Route connections to be forwarded through lo
route add -net <net to be routed> netmask <netmask for net> dev lo

# Dont reroute normal loopback traffic
ipfwadm -I -a accept -D 127.0.0.0/8 -W lo

# Reroute connections to be forwarded
ipfwadm -I -a accept -P tcp -D 0/0 -W lo -r <someport>

# Tell ssh to forward
ssh <normal connection information> -L <someport>:DYN:0

# end






diff -u -r ssh-1.2.21-old/newchannels.c ssh-1.2.21/newchannels.c
--- newchannels.c	Fri Aug 22 02:28:27 1997
+++ newchannels.c	Tue Oct 13 23:53:43 1998
@@ -969,8 +969,27 @@
 				       xstrdup(buf));
 	      packet_start(SSH_MSG_PORT_OPEN);
 	      packet_put_int(newch);
-	      packet_put_string(ch->path, strlen(ch->path));
-	      packet_put_int(ch->host_port);
+	      if (strcmp(ch->path,"DYN")) {
+		packet_put_string(ch->path, strlen(ch->path));
+		packet_put_int(ch->host_port);
+	      } else {
+		struct sockaddr_in dyntarg;
+		size_t dyntargsize;
+		const char *dyn_host;
+		int dyn_port;
+
+		dyntargsize = sizeof(dyntarg);
+		if (getsockname(newsock,(struct sockaddr *)&dyntarg, &dyntargsize)<0) {
+		  error("getsockname: %.100s", strerror(errno));
+		  channel_free(newch);
+		  break;
+		};
+		dyn_host = inet_ntoa(dyntarg.sin_addr);
+		dyn_port = htons(dyntarg.sin_port);
+		log_msg("Dyncamic channel to %.30s:%d",dyn_host,dyn_port);
+		packet_put_string(dyn_host,strlen(dyn_host));
+		packet_put_int(dyn_port);
+	      };
 	      if (have_hostname_in_open)
 		packet_put_string(buf, strlen(buf));
 	      packet_send();



[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic