Bug 2820 - Add support for ssh client to bind to an interface
Summary: Add support for ssh client to bind to an interface
Status: CLOSED FIXED
Alias: None
Product: Portable OpenSSH
Classification: Unclassified
Component: ssh (show other bugs)
Version: 7.6p1
Hardware: Other Linux
: P5 enhancement
Assignee: Damien Miller
URL:
Keywords:
Depends on:
Blocks: V_7_7
  Show dependency treegraph
 
Reported: 2018-01-10 04:39 AEDT by Mike Manning
Modified: 2023-01-13 13:40 AEDT (History)
2 users (show)

See Also:


Attachments
Suggested diff (8.67 KB, text/plain)
2018-01-10 04:39 AEDT, Mike Manning
no flags Details
revised diff (10.98 KB, patch)
2018-02-16 15:37 AEDT, Damien Miller
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Mike Manning 2018-01-10 04:39:57 AEDT
Created attachment 3114 [details]
Suggested diff

While the ssh client can bind to a specified source address, the caller
needs to have resolved the host beforehand so as to know to pass an IPv4
or IPv6 address. By instead specifying an interface to bind to, the ssh
client can select a suitable address of the correct family configured on
this interface. More importantly, this allows the source addresses to be
modified without each time having to update the ssh config. A common
usecase on networking devices is to specify typically a loopback
interface on which the addresses to bind to are configured.
Comment 1 Damien Miller 2018-02-16 13:45:27 AEDT
This looks like a useful feature - thanks.

One nit:

+			if (strncmp(ifa->ifa_name, options.bind_interface,
+				    IFNAMSIZ))
+				continue;

I think this should be plain strcmp otherwise matching, say, "tun1" against "tun11" will succeed where it shouldn't.
Comment 2 Damien Miller 2018-02-16 15:37:03 AEDT
Created attachment 3121 [details]
revised diff

This fixes the strcmp thing I mentioned above as well as a few other small things. Notably, it only considers interfaces in state UP and will fallback to accepting linklocal/loopback addresses after all other possibilities have been exhausted.
Comment 3 Mike Manning 2018-02-17 04:36:23 AEDT
Many thanks for looking into this enhancement, which will make deployment for us a lot easier. I excluded the IPv6 loopback addr ::1, as it should not be used as the source address in packets that are sent outside of the node cf RFC4291, section 2.5.3. Also I excluded link-local addresses, as these could only work with a directly connected ssh server, also for reasons of parity with the bind address option, which errors as follows:

ssh -b fe80::5054:ff:fe4d:a73 mike@VR3v6
bind: fe80::5054:ff:fe4d:a73: Invalid argument
ssh: connect to host vr3v6 port 22: Invalid argument

I confirm I have tested your changes, which are fine for loopback with IPv4 & IPv6 addr, IPv4 only, IPv6 only (apart from my concerns re use of IPv6 loopback & LL), and even if there is only an IPv6 link-local address, the end result is ok:

ssh -B lo2 mike@VR4v6
debug2: resolving "vr4v6" port 22
debug2: ssh_connect_direct: needpriv 0
debug1: Connecting to vr4v6 [2000::4] port 22.
debug1: ssh_create_socket: bound to fe80::fc55:b3ff:fee5:d46%lo2
debug1: connect to address 2000::4 port 22: Network is unreachable
ssh: connect to host vr4v6 port 22: Network is unreachable

I am fine with use of strcmp, I just wanted to point out that I was using strncmp with the length check using the maximum string size for interface names IFNAMSIZ (=16), so substring matches don't occur, but this approach avoids problems with strings that are not null-terminated (I appreciate that is not the case here!). Thanks again.
Comment 4 Mike Manning 2018-02-17 21:23:22 AEDT
Just to confirm that my testing is with a loopback interface (I have also tried eth intf) as the bind interface, with IPv4 and/or global IPv6 address(es) configured on that. I approve your changes (also your changes for #2814, thanks), with the proviso that I would prefer for the IPv6 loopback address (::1) and link-local addresses to be excluded for the reasons mentioned. Thanks also for the catch on checking that the bind interface needs to be up.
Comment 5 Damien Miller 2018-02-20 16:19:31 AEDT
IMO we should relax the restrictions for loopback and link-local addresses for BindAddress too.

It's fine to use SSH to a loopback address (e.g. tunnelling / NAT / virtualisation) and definitiely fine to use it on a link-local address too.
Comment 6 Damien Miller 2018-02-23 13:33:01 AEDT
This has been applied and will be in OpenSSH 7.7 - thanks!

commit ac2e3026bbee1367e4cda34765d1106099be3287 (HEAD -> master, origin/master, origin/HEAD)
Author: djm@openbsd.org <djm@openbsd.org>
Date:   Fri Feb 23 02:34:33 2018 +0000

    upstream: Add BindInterface ssh_config directive and -B
    
    command-line argument to ssh(1) that directs it to bind its outgoing
    connection to the address of the specified network interface.
    
    BindInterface prefers to use addresses that aren't loopback or link-
    local, but will fall back to those if no other addresses of the
    required family are available on that interface.
    
    Based on patch by Mike Manning in bz#2820, ok dtucker@
    
    OpenBSD-Commit-ID: c5064d285c2851f773dd736a2c342aa384fbf713
Comment 7 Damien Miller 2021-04-23 15:04:34 AEST
closing resolved bugs as of 8.6p1 release