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();