noah williamsson
2009-Jul-09 17:21 UTC
[PATCH] Allow binding to a local port (OpenSSH 5.2)
OpenSSH supports the -b bind_address argument for binding to a local IP address when connecting to a remote host. It's however currently not possible to specify a local port to bind to, something I've found useful at several occasions. Below is an unified diff that introduces the [-B bind_port] option to ssh(1) and a ssh_config(5) style option "BindPort bind_port". This allows for binding the clientside programs to a specified local port when outgoing connections are made. Note: I didn't bother updating the man pages at this stage but I could if it sounds interesting. The patch is based on OpenSSH 5.2p1 but applies to OpenSSH 5.2 too. I've found this patch working on decent releases of Ubuntu aswell as Mac OS X Leopard. Feedback is welcome. Please CC me if you reply to the list as I'm not subscribed. diff -ruN a/readconf.c b/readconf.c --- a/readconf.c 2009-02-14 06:28:21.000000000 +0100 +++ b/readconf.c 2009-07-09 18:24:09.000000000 +0200 @@ -123,7 +123,7 @@ oGlobalKnownHostsFile2, oUserKnownHostsFile2, oPubkeyAuthentication, oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias, oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication, - oHostKeyAlgorithms, oBindAddress, oSmartcardDevice, + oHostKeyAlgorithms, oBindAddress, oBindPort, oSmartcardDevice, oClearAllForwardings, oNoHostAuthenticationForLocalhost, oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout, oAddressFamily, oGssAuthentication, oGssDelegateCreds, @@ -205,6 +205,7 @@ { "preferredauthentications", oPreferredAuthentications }, { "hostkeyalgorithms", oHostKeyAlgorithms }, { "bindaddress", oBindAddress }, + { "bindport", oBindPort }, #ifdef SMARTCARD { "smartcarddevice", oSmartcardDevice }, #else @@ -608,6 +609,10 @@ charptr = &options->bind_address; goto parse_string; + case oBindPort: + charptr = &options->bind_port; + goto parse_string; + case oSmartcardDevice: charptr = &options->smartcard_device; goto parse_string; @@ -1046,6 +1051,7 @@ options->log_level = SYSLOG_LEVEL_NOT_SET; options->preferred_authentications = NULL; options->bind_address = NULL; + options->bind_port = NULL; options->smartcard_device = NULL; options->enable_ssh_keysign = - 1; options->no_host_authentication_for_localhost = - 1; diff -ruN a/readconf.h b/readconf.h --- a/readconf.h 2009-02-14 06:28:21.000000000 +0100 +++ b/readconf.h 2009-07-09 18:17:36.000000000 +0200 @@ -84,6 +84,7 @@ char *user_hostfile2; char *preferred_authentications; char *bind_address; /* local socket address for connection to sshd */ + char *bind_port; /* local socket source port for connection to sshd */ char *smartcard_device; /* Smartcard reader device */ int verify_host_key_dns; /* Verify host key using DNS */ diff -ruN a/ssh.c b/ssh.c --- a/ssh.c 2009-02-14 06:28:21.000000000 +0100 +++ b/ssh.c 2009-07-09 18:35:12.000000000 +0200 @@ -179,10 +179,11 @@ usage(void) { fprintf(stderr, -"usage: ssh [-1246AaCfgKkMNnqsTtVvXxYy] [-b bind_address] [-c cipher_spec]\n" -" [-D [bind_address:]port] [-e escape_char] [-F configfile]\n" -" [-i identity_file] [-L [bind_address:]port:host:hostport]\n" -" [-l login_name] [-m mac_spec] [-O ctl_cmd] [-o option] [-p port]\n" +"usage: ssh [-1246AaCfgKkMNnqsTtVvXxYy] [-b bind_address] [-B bind_port ]\n" +" [-c cipher_spec] [-D [bind_address:]port] [-e escape_char]\n" +" [-F configfile] [-i identity_file]\n" +" [-L [bind_address:]port:host:hostport] [-l login_name]\n" +" [-m mac_spec] [-O ctl_cmd] [-o option] [-p port]\n" " [-R [bind_address:]port:host:hostport] [-S ctl_path]\n" " [-w local_tun[:remote_tun]] [user@]hostname [command]\n" ); @@ -272,7 +273,7 @@ use_syslog = 0; again: - while ((opt = getopt(ac, av, "1246ab:c:e:fgi:kl:m:no:p:qstvx" + while ((opt = getopt(ac, av, "1246ab:B:c:e:fgi:kl:m:no:p:qstvx" "ACD:F:I:KL:MNO:PR:S:TVw:XYy")) != -1) { switch (opt) { case '1': @@ -514,6 +515,9 @@ case 'b': options.bind_address = optarg; break; + case 'B': + options.bind_port = optarg; + break; case 'F': config = optarg; break; diff -ruN a/sshconnect.c b/sshconnect.c --- a/sshconnect.c 2009-02-01 12:19:54.000000000 +0100 +++ b/sshconnect.c 2009-07-09 18:39:21.000000000 +0200 @@ -194,7 +194,7 @@ error("socket: %.100s", strerror(errno)); /* Bind the socket to an alternative local IP address */ - if (options.bind_address == NULL) + if (options.bind_address == NULL && options.bind_port == NULL) return sock; memset(&hints, 0, sizeof(hints)); @@ -202,7 +202,7 @@ hints.ai_socktype = ai->ai_socktype; hints.ai_protocol = ai->ai_protocol; hints.ai_flags = AI_PASSIVE; - gaierr = getaddrinfo(options.bind_address, NULL, &hints, &res); + gaierr = getaddrinfo(options.bind_address, options.bind_port, &hints, &res); if (gaierr) { error("getaddrinfo: %s: %s", options.bind_address, ssh_gai_strerror(gaierr)); @@ -210,7 +210,10 @@ return -1; } if (bind(sock, res->ai_addr, res->ai_addrlen) < 0) { - error("bind: %s: %s", options.bind_address, strerror(errno)); + error("bind: %s port %s: %s", + options.bind_address? options.bind_address: "0.0.0.0", + options.bind_port? options.bind_port: "0", + strerror(errno)); close(sock); freeaddrinfo(res); return -1; -- Best regards, Noah Williamsson