Bugzilla – Attachment 3114 Details for
Bug 2820
Add support for ssh client to bind to an interface
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
Suggested diff
diffs-ssh-bind-interface.txt (text/plain), 8.67 KB, created by
Mike Manning
on 2018-01-10 04:39:57 AEDT
(
hide
)
Description:
Suggested diff
Filename:
MIME Type:
Creator:
Mike Manning
Created:
2018-01-10 04:39:57 AEDT
Size:
8.67 KB
patch
obsolete
>diff --git a/readconf.c b/readconf.c >index 10b57bd..5cfee4d 100644 >--- a/readconf.c >+++ b/readconf.c >@@ -156,7 +156,7 @@ typedef enum { > oPubkeyAuthentication, > oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias, > oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication, >- oHostKeyAlgorithms, oBindAddress, oPKCS11Provider, >+ oHostKeyAlgorithms, oBindAddress, oBindInterface, oPKCS11Provider, > oClearAllForwardings, oNoHostAuthenticationForLocalhost, > oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout, > oAddressFamily, oGssAuthentication, oGssDelegateCreds, >@@ -266,6 +266,7 @@ static struct { > { "preferredauthentications", oPreferredAuthentications }, > { "hostkeyalgorithms", oHostKeyAlgorithms }, > { "bindaddress", oBindAddress }, >+ { "bindinterface", oBindInterface }, > { "clearallforwardings", oClearAllForwardings }, > { "enablesshkeysign", oEnableSSHKeysign }, > { "verifyhostkeydns", oVerifyHostKeyDNS }, >@@ -1099,6 +1100,10 @@ parse_char_array: > charptr = &options->bind_address; > goto parse_string; > >+ case oBindInterface: >+ charptr = &options->bind_interface; >+ goto parse_string; >+ > case oPKCS11Provider: > charptr = &options->pkcs11_provider; > goto parse_string; >@@ -1800,6 +1805,7 @@ initialize_options(Options * options) > options->log_level = SYSLOG_LEVEL_NOT_SET; > options->preferred_authentications = NULL; > options->bind_address = NULL; >+ options->bind_interface = NULL; > options->pkcs11_provider = NULL; > options->enable_ssh_keysign = - 1; > options->no_host_authentication_for_localhost = - 1; >@@ -2509,6 +2515,7 @@ dump_client_config(Options *o, const char *host) > > /* String options */ > dump_cfg_string(oBindAddress, o->bind_address); >+ dump_cfg_string(oBindInterface, o->bind_interface); > dump_cfg_string(oCiphers, o->ciphers ? o->ciphers : KEX_CLIENT_ENCRYPT); > dump_cfg_string(oControlPath, o->control_path); > dump_cfg_string(oHostKeyAlgorithms, o->hostkeyalgorithms); >diff --git a/readconf.h b/readconf.h >index 34aad83..da1e6d0 100644 >--- a/readconf.h >+++ b/readconf.h >@@ -81,6 +81,7 @@ typedef struct { > char *user_hostfiles[SSH_MAX_HOSTS_FILES]; > char *preferred_authentications; > char *bind_address; /* local socket address for connection to sshd */ >+ char *bind_interface; /* local interface for bind address */ > char *pkcs11_provider; /* PKCS#11 provider */ > int verify_host_key_dns; /* Verify host key using DNS */ > >diff --git a/ssh.1 b/ssh.1 >index 9de2a11..a3105c9 100644 >--- a/ssh.1 >+++ b/ssh.1 >@@ -43,6 +43,7 @@ > .Sh SYNOPSIS > .Nm ssh > .Op Fl 46AaCfGgKkMNnqsTtVvXxYy >+.Op Fl B Ar bind_interface > .Op Fl b Ar bind_address > .Op Fl c Ar cipher_spec > .Op Fl D Oo Ar bind_address : Oc Ns Ar port >@@ -124,6 +125,15 @@ authenticate using the identities loaded into the agent. > .It Fl a > Disables forwarding of the authentication agent connection. > .Pp >+.It Fl B Ar bind_interface >+Use >+.Ar bind_interface >+on the local machine as the interface to obtain the IPv4 or IPv6 source address >+of the connection from. This allows the address family not to be known apriori >+and allows the addresses to be changed on typically a loopback interface without >+modifying how ssh is called. The bind_address option takes precedence over this. >+Only useful on systems with more than one address. >+.Pp > .It Fl b Ar bind_address > Use > .Ar bind_address >diff --git a/ssh.c b/ssh.c >index 8626254..1f43bcb 100644 >--- a/ssh.c >+++ b/ssh.c >@@ -201,13 +201,13 @@ static void > usage(void) > { > fprintf(stderr, >-"usage: ssh [-46AaCfGgKkMNnqsTtVvXxYy] [-b bind_address] [-c cipher_spec]\n" >-" [-D [bind_address:]port] [-E log_file] [-e escape_char]\n" >-" [-F configfile] [-I pkcs11] [-i identity_file]\n" >-" [-J [user@]host[:port]] [-L address] [-l login_name] [-m mac_spec]\n" >-" [-O ctl_cmd] [-o option] [-p port] [-Q query_option] [-R address]\n" >-" [-S ctl_path] [-W host:port] [-w local_tun[:remote_tun]]\n" >-" destination [command]\n" >+"usage: ssh [-46AaCfGgKkMNnqsTtVvXxYy] [-B bind_interface]\n" >+" [-b bind_address] [-c cipher_spec] [-D [bind_address:]port]\n" >+" [-E log_file] [-e escape_char] [-F configfile] [-I pkcs11]\n" >+" [-i identity_file] [-J [user@]host[:port]] [-L address]\n" >+" [-l login_name] [-m mac_spec] [-O ctl_cmd] [-o option] [-p port]\n" >+" [-Q query_option] [-R address] [-S ctl_path] [-W host:port]\n" >+" [-w local_tun[:remote_tun]] destination [command]\n" > ); > exit(255); > } >@@ -615,7 +615,7 @@ main(int ac, char **av) > > again: > while ((opt = getopt(ac, av, "1246ab:c:e:fgi:kl:m:no:p:qstvx" >- "ACD:E:F:GI:J:KL:MNO:PQ:R:S:TVw:W:XYy")) != -1) { >+ "AB:CD:E:F:GI:J:KL:MNO:PQ:R:S:TVw:W:XYy")) != -1) { > switch (opt) { > case '1': > fatal("SSH protocol v.1 is no longer supported"); >@@ -925,6 +925,9 @@ main(int ac, char **av) > case 'b': > options.bind_address = optarg; > break; >+ case 'B': >+ options.bind_interface = optarg; >+ break; > case 'F': > config = optarg; > break; >diff --git a/sshconnect.c b/sshconnect.c >index 4497770..f8b61af 100644 >--- a/sshconnect.c >+++ b/sshconnect.c >@@ -23,6 +23,7 @@ > # include <sys/time.h> > #endif > >+#include <net/if.h> > #include <netinet/in.h> > #include <arpa/inet.h> > >@@ -43,6 +44,7 @@ > #include <stdlib.h> > #include <string.h> > #include <unistd.h> >+#include <ifaddrs.h> > > #include "xmalloc.h" > #include "key.h" >@@ -276,8 +278,15 @@ ssh_kill_proxy_command(void) > static int > ssh_create_socket(int privileged, struct addrinfo *ai) > { >- int sock, r, gaierr; >- struct addrinfo hints, *res = NULL; >+ int sock, r, gaierr, err; >+ struct addrinfo hints, result; >+ struct addrinfo *info = NULL; >+ struct addrinfo *res = NULL; >+ struct ifaddrs *ifaddrs = NULL; >+ struct ifaddrs *ifa; >+ struct sockaddr_in6 *sa6; >+ struct sockaddr_in *sa; >+ struct in6_addr *v6addr; > > sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); > if (sock < 0) { >@@ -287,7 +296,8 @@ ssh_create_socket(int privileged, struct addrinfo *ai) > fcntl(sock, F_SETFD, FD_CLOEXEC); > > /* Bind the socket to an alternative local IP address */ >- if (options.bind_address == NULL && !privileged) >+ if ((options.bind_address == NULL && options.bind_interface == NULL) && >+ !privileged) > return sock; > > if (options.bind_address) { >@@ -300,8 +310,52 @@ ssh_create_socket(int privileged, struct addrinfo *ai) > if (gaierr) { > error("getaddrinfo: %s: %s", options.bind_address, > ssh_gai_strerror(gaierr)); >- close(sock); >- return -1; >+ goto fail; >+ } >+ info = res; >+ } else if (options.bind_interface) { >+ err = getifaddrs(&ifaddrs); >+ if (err) { >+ error("getifaddrs: %s: %s", options.bind_interface, >+ strerror(err)); >+ goto fail; >+ } >+ for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) { >+ if (!ifa->ifa_addr) >+ continue; >+ >+ if (strncmp(ifa->ifa_name, options.bind_interface, >+ IFNAMSIZ)) >+ continue; >+ >+ if (ifa->ifa_addr->sa_family != ai->ai_family) >+ continue; >+ >+ if (ifa->ifa_addr->sa_family == AF_INET) { >+ sa = (struct sockaddr_in *)ifa->ifa_addr; >+ if (sa->sin_addr.s_addr == >+ htonl(INADDR_LOOPBACK)) >+ continue; >+ } else if (ifa->ifa_addr->sa_family == AF_INET6) { >+ sa6 = (struct sockaddr_in6 *)ifa->ifa_addr; >+ v6addr = &sa6->sin6_addr; >+ if (IN6_IS_ADDR_LINKLOCAL(v6addr) || >+ IN6_IS_ADDR_LOOPBACK(v6addr)) >+ continue; >+ } >+ >+ result.ai_addr = ifa->ifa_addr; >+ result.ai_family = ifa->ifa_addr->sa_family; >+ result.ai_addrlen = (result.ai_family == AF_INET >+ ? sizeof(struct sockaddr_in) >+ : sizeof(struct sockaddr_in6)); >+ info = &result; >+ break; >+ } >+ if (!info) { >+ logit("getifaddrs: %s: no suitable addresses found", >+ options.bind_interface); >+ goto fail; > } > } > /* >@@ -310,7 +364,7 @@ ssh_create_socket(int privileged, struct addrinfo *ai) > */ > if (privileged) { > PRIV_START; >- r = bindresvport_sa(sock, res ? res->ai_addr : NULL); >+ r = bindresvport_sa(sock, info ? info->ai_addr : NULL); > PRIV_END; > if (r < 0) { > error("bindresvport_sa: af=%d %s", ai->ai_family, >@@ -318,18 +372,25 @@ ssh_create_socket(int privileged, struct addrinfo *ai) > goto fail; > } > } else { >- if (bind(sock, res->ai_addr, res->ai_addrlen) < 0) { >- error("bind: %s: %s", options.bind_address, >- strerror(errno)); >- fail: >- close(sock); >- freeaddrinfo(res); >- return -1; >+ if (bind(sock, info->ai_addr, info->ai_addrlen) < 0) { >+ error("bind: %s: %s", options.bind_address ? >+ options.bind_address : options.bind_interface, >+ strerror(errno)); >+ goto fail; > } > } > if (res != NULL) > freeaddrinfo(res); >+ if (ifaddrs) >+ freeifaddrs(ifaddrs); > return sock; >+fail: >+ close(sock); >+ if (res) >+ freeaddrinfo(res); >+ if (ifaddrs) >+ freeifaddrs(ifaddrs); >+ return -1; > } > > /*
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Actions:
View
Attachments on
bug 2820
:
3114
|
3121