Hi,
I'm not a subscriber to this list so please CC: me in any replies.
I found myself in a situation where I was behind a corporate firewall
that allowed only web requests to the outside world (and furthermore
those requests had to be via their proxy server). Therefore, I couldn't
SSH to the outside world.
However, the HTTP proxy 'CONNECT' method, which is normally used to
support SSL requests, can be used to do this. This worked great for me.
Attached is a patch to SSH version 2.9 (comes with FreeBSD 4.5-REL)
to implement 'ProxyServer' and 'ProxyPort' options, also
specifiable
on the command line using '-r'.
E.g.:
ssh -r 10.12.114.3:8080 foobar at some.server.com
Then ssh will go through the HTTP proxy at 10.12.114.3 8080
and tell it to 'CONNECT' to 'some.server.com:22'.
I found it useful so perhaps others would too. Please let me know
whether or not you decide to include it in the standard SSH.
Thanks,
-Archie
__________________________________________________________________________
Archie Cobbs * Packet Design * http://www.packetdesign.com
-------------- next part --------------
diff -ur -x CVS /usr/src/crypto/openssh/readconf.c src/readconf.c
--- /usr/src/crypto/openssh/readconf.c Thu Sep 27 18:33:34 2001
+++ src/readconf.c Wed Jul 17 16:14:44 2002
@@ -108,6 +108,7 @@
#endif
oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward,
oUser, oHost, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand,
+ oProxyServer, oProxyPort,
oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts,
oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression,
oCompressionLevel, oKeepAlives, oNumberOfPasswordPrompts,
@@ -158,6 +159,8 @@
{ "hostname", oHostName },
{ "hostkeyalias", oHostKeyAlias },
{ "proxycommand", oProxyCommand },
+ { "proxyserver", oProxyServer },
+ { "proxyport", oProxyPort },
{ "port", oPort },
{ "cipher", oCipher },
{ "ciphers", oCiphers },
@@ -484,6 +487,14 @@
xfree(string);
return 0;
+ case oProxyServer:
+ charptr = &options->proxy_server;
+ goto parse_string;
+
+ case oProxyPort:
+ intptr = &options->proxy_port;
+ goto parse_int;
+
case oPort:
intptr = &options->port;
parse_int:
@@ -765,6 +776,8 @@
options->hostname = NULL;
options->host_key_alias = NULL;
options->proxy_command = NULL;
+ options->proxy_server = NULL;
+ options->proxy_port = -1;
options->user = NULL;
options->escape_char = -1;
options->system_hostfile = NULL;
@@ -894,6 +907,7 @@
if (options->log_level == (LogLevel) - 1)
options->log_level = SYSLOG_LEVEL_INFO;
/* options->proxy_command should not be set by default */
+ /* options->proxy_server should not be set by default */
/* options->user will be set in the main program if appropriate */
/* options->hostname will be set in the main program if appropriate */
/* options->host_key_alias should not be set by default */
diff -ur -x CVS /usr/src/crypto/openssh/readconf.h src/readconf.h
--- /usr/src/crypto/openssh/readconf.h Thu Sep 27 18:33:34 2001
+++ src/readconf.h Wed Jul 17 16:14:44 2002
@@ -83,6 +83,8 @@
char *hostname; /* Real host to connect. */
char *host_key_alias; /* hostname alias for .ssh/known_hosts */
char *proxy_command; /* Proxy command for connecting the host. */
+ char *proxy_server; /* HTTP proxy server to relay through. */
+ int proxy_port; /* HTTP proxy server port. */
char *user; /* User to log in as. */
int escape_char; /* Escape character; -2 = none */
diff -ur -x CVS /usr/src/crypto/openssh/ssh.c src/ssh.c
--- /usr/src/crypto/openssh/ssh.c Thu Sep 27 18:33:35 2001
+++ src/ssh.c Wed Jul 17 16:14:44 2002
@@ -175,6 +175,7 @@
fprintf(stderr, " -R listen-port:host:port Forward remote port to
local address\n");
fprintf(stderr, " These cause %s to listen for connections
on a port, and\n", __progname);
fprintf(stderr, " forward them to the other side by
connecting to host:port.\n");
+ fprintf(stderr, " -r host:prt Connect using specified HTTP
proxy.\n");
fprintf(stderr, " -C Enable compression.\n");
fprintf(stderr, " -N Do not execute a shell or
command.\n");
fprintf(stderr, " -g Allow remote hosts to connect to forwarded
ports.\n");
@@ -309,7 +310,7 @@
opt = av[optind][1];
if (!opt)
usage();
- if (strchr("eilcmpLRDo", opt)) { /* options with arguments */
+ if (strchr("eilcmpLRDor", opt)) { /* options with arguments */
optarg = av[optind] + 2;
if (strcmp(optarg, "") == 0) {
if (optind >= ac - 1)
@@ -481,6 +482,15 @@
/* NOTREACHED */
}
add_local_forward(&options, fwd_port, buf, fwd_host_port);
+ break;
+ case 'r':
+ if (sscanf(optarg, "%255[^:]:%u", buf,
+ &options.proxy_port) != 2) {
+ fprintf(stderr, "Bad HTTP proxy '%s'.\n", optarg);
+ usage();
+ /* NOTREACHED */
+ }
+ options.proxy_server = xstrdup(buf);
break;
case 'D':
diff -ur -x CVS /usr/src/crypto/openssh/sshconnect.c src/sshconnect.c
--- /usr/src/crypto/openssh/sshconnect.c Thu Sep 27 18:33:35 2001
+++ src/sshconnect.c Wed Jul 17 16:14:44 2002
@@ -198,7 +198,9 @@
int gaierr;
int on = 1;
int sock = -1, attempt;
+ int connect_port;
char ntop[NI_MAXHOST], strport[NI_MAXSERV];
+ const char *connect_host;
struct addrinfo hints, *ai, *aitop;
struct linger linger;
struct servent *sp;
@@ -218,14 +220,21 @@
if (proxy_command != NULL)
return ssh_proxy_connect(host, port, pw, proxy_command);
- /* No proxy command. */
+ /* If an HTTP proxy is given, connect to it first. */
+ if (options.proxy_server != NULL) {
+ connect_host = options.proxy_server;
+ connect_port = options.proxy_port;
+ } else {
+ connect_host = host;
+ connect_port = port;
+ }
memset(&hints, 0, sizeof(hints));
hints.ai_family = IPv4or6;
hints.ai_socktype = SOCK_STREAM;
- snprintf(strport, sizeof strport, "%d", port);
- if ((gaierr = getaddrinfo(host, strport, &hints, &aitop)) != 0)
- fatal("%s: %.100s: %s", __progname, host,
+ snprintf(strport, sizeof strport, "%d", connect_port);
+ if ((gaierr = getaddrinfo(connect_host, strport, &hints, &aitop)) !=
0)
+ fatal("%s: %.100s: %s", __progname, connect_host,
gai_strerror(gaierr));
/*
@@ -293,6 +302,29 @@
/* Return failure if we didn't get a successful connection. */
if (attempt >= connection_attempts)
return 0;
+
+ /* Connect through HTTP proxy. */
+ if (options.proxy_server != NULL) {
+ char buf[512];
+ int state;
+ char byte;
+
+ debug("Sending proxy CONNECT.");
+
+ snprintf(buf, sizeof(buf), "CONNECT %s:%d HTTP/1.0\r\n\r\n",
+ host, port);
+ write(sock, buf, strlen(buf));
+ for (state = 0; state < 4; ) {
+ if (read(sock, &byte, 1) != 1)
+ return 0;
+ if (byte == ((state & 1) ? '\n' : '\r'))
+ state++;
+ else
+ state = 0;
+ }
+
+ debug("Read proxy response.");
+ }
debug("Connection established.");