Patch for SSH-tunneling via HTTPS-proxy

Leif Jakob openssh at jakob.weite-welt.com
Thu Oct 18 21:44:30 EST 2001


Hi List,

I have a szenario where I need to reach a host on the internet from a
"firewalled" network but there is a HTTPS-proxy runnnig. As some
people know you can tunnel all TCP-connections through this proxy
because it can't decide if someone is really doing SSL or just Telnet
to port 443 (or use SSH in our case).

So I've written a patch for ssh to make it send the 

CONNECT $host:$port HTTP/1.0\r\n\r\n

to the proxy. The new call is now:

ssh -p 3128 -H host.on.internet.org:443 myuser at local.proxy

All you need is a SSH-Server running on port 443 on
host.on.internet.org, or if the proxy allows (squid doesn't) port 22.


Cheers

Leif

diff --unified --recursive openssh-2.9.9p2.orig/readconf.c openssh-2.9.9p2.httpsproxy/readconf.c
--- openssh-2.9.9p2.orig/readconf.c	Thu Oct 18 11:53:43 2001
+++ openssh-2.9.9p2.httpsproxy/readconf.c	Thu Oct 18 11:55:48 2001
@@ -789,6 +789,7 @@
 	options->num_local_forwards = 0;
 	options->num_remote_forwards = 0;
 	options->clear_forwardings = -1;
+	options->https_proxy = NULL;
 	options->log_level = (LogLevel) - 1;
 	options->preferred_authentications = NULL;
 	options->bind_address = NULL;
diff --unified --recursive openssh-2.9.9p2.orig/readconf.h openssh-2.9.9p2.httpsproxy/readconf.h
--- openssh-2.9.9p2.orig/readconf.h	Thu Oct 18 11:53:43 2001
+++ openssh-2.9.9p2.httpsproxy/readconf.h	Thu Oct 18 11:55:09 2001
@@ -101,6 +101,10 @@
 	int     num_remote_forwards;
 	Forward remote_forwards[SSH_MAX_FORWARDS_PER_DIRECTION];
 	int	clear_forwardings;
+
+        /* https proxy options */ 
+	char   *https_proxy;	/* connect string to send to https-proxy */
+
 }       Options;
 
 
diff --unified --recursive openssh-2.9.9p2.orig/ssh.c openssh-2.9.9p2.httpsproxy/ssh.c
--- openssh-2.9.9p2.orig/ssh.c	Thu Oct 18 11:53:43 2001
+++ openssh-2.9.9p2.httpsproxy/ssh.c	Thu Oct 18 13:41:07 2001
@@ -205,6 +205,7 @@
 	fprintf(stderr, "  -o 'option' Process the option as if it was read from a configuration file.\n");
 	fprintf(stderr, "  -s          Invoke command (mandatory) as SSH2 subsystem.\n");
 	fprintf(stderr, "  -b addr     Local IP address.\n");
+	fprintf(stderr, "  -H 'realhost:port'  do HTTPS-proxy negotiation before expecting SSH-version\n");
 	exit(1);
 }
 
@@ -320,7 +321,7 @@
 
 again:
 	while ((opt = getopt(ac, av,
-	    "1246ab:c:e:fgi:kl:m:no:p:qstvxACD:F:I:L:NPR:TVX")) != -1) {
+	    "1246ab:c:e:fgi:kl:m:no:p:qstvxACD:F:I:L:NPR:TVXH:")) != -1) {
 		switch (opt) {
 		case '1':
 			options.protocol = SSH_PROTO_1;
@@ -530,6 +531,9 @@
 			break;
 		case 'F':
 			config = optarg;
+			break;
+		case 'H':
+		        options.https_proxy = optarg;
 			break;
 		default:
 			usage();
diff --unified --recursive openssh-2.9.9p2.orig/sshconnect.c openssh-2.9.9p2.httpsproxy/sshconnect.c
--- openssh-2.9.9p2.orig/sshconnect.c	Thu Oct 18 11:53:43 2001
+++ openssh-2.9.9p2.httpsproxy/sshconnect.c	Thu Oct 18 13:20:43 2001
@@ -387,6 +387,34 @@
 	return 0;
 }
 
+/* uses "CONNECT %s HTTP/1.0\r\n\r\n" to access real host via https-proxy 
+ * the SSH-handshake code will handle results from the proxy
+ *
+ * this nice patch was brought to you by Leif Jakob <openssh at jakob.weite-welt.com>, don't blame me
+ * if someone is abusing your misconfigured proxies :) but some broken firewalls require this feature
+ */
+void
+https_proxy_handshake(const char *connect_string)
+{
+  int connection_out = packet_get_connection_out();
+
+#define PROXY1 "CONNECT "
+#define PROXY3 " HTTP/1.0\r\n\r\n"
+
+  if (atomicio(write, connection_out, PROXY1, sizeof(PROXY1)-1) != sizeof(PROXY1)-1)
+    fatal("write proxy1: %.100s", strerror(errno));
+
+  if (atomicio(write, connection_out, (void *)connect_string, strlen(connect_string)) != strlen(connect_string))
+    fatal("write proxy2: %.100s", strerror(errno));
+
+  if (atomicio(write, connection_out, PROXY3, sizeof(PROXY3)-1) != sizeof(PROXY3)-1)
+    fatal("write proxy3: %.100s", strerror(errno));
+  
+#undef PROXY1
+#undef PROXY3
+
+}
+
 /*
  * Waits for the server identification string, and sends our own
  * identification string.
@@ -883,6 +911,10 @@
 	for (cp = host; *cp; cp++)
 		if (isupper(*cp))
 			*cp = tolower(*cp);
+
+	/* do https-handshake with HTTPS-proxy we abuse for SSH tunneling */
+	if ( options.https_proxy )
+	  https_proxy_handshake(options.https_proxy);
 
 	/* Exchange protocol version identification strings with the server. */
 	ssh_exchange_identification();



More information about the openssh-unix-dev mailing list