[PATCH] Allow binding to a local port (OpenSSH 5.2)

noah williamsson noah.williamsson at gmail.com
Fri Jul 10 03:21:00 EST 2009


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


More information about the openssh-unix-dev mailing list