tunnel device name acquisition?

Gabriel L. Somlo gsomlo at gmail.com
Fri Oct 13 09:06:30 AEDT 2017


On Thu, Oct 12, 2017 at 10:05:02AM +1100, Damien Miller wrote:
> 
> 
> On Tue, 10 Oct 2017, Gabriel L. Somlo wrote:
> 
> > Numerous how-tos all over the Internet show how one would set up
> > a tunnel using ssh, e.g.:
> > 
> > 	ssh -f -o Tunnel=ethernet <server_ip> true
> > 
> > I was wondering if there's a way to subsequently acquire the names
> > of the local and remote tun/tap interfaces (e.g., using the default
> > "-w any:any") for subsequent automatic tunnel configuration, e.g.:
> > 
> > 	ip link set $TapDev up
> > 	ip link set $TapDev master <client-or-server-side-bridge>
> > 
> > Most examples out there pick something silly like "-w 5:5" then
> > proceed to configure the hard-coded "tap5" on both client and server.
> > However, that's unreliable -- what if "tap5" is already in use on the
> > server, and we have to pick something else? What if I want to set up a
> > server to accept multiple connections from random clients in random
> > order?
> > 
> > Ideally, I'd start ssh-based "tunnel client" and "tunnel server"
> > services at boot, and having to pick names manually, then manually
> > configure everything on both ends is quite limiting.
> > 
> > I tried starting the client with "-vvv" hoping the verbose debugging
> > output would include some grep-able hint as to what interface names
> > were picked, but couldn't see anything useful.
> 
> The following might do what you want; on the client side it expands
> %T tokens in LocalCommand to the local tunnel device name and exposes
> the remote device name via $SSH_TUNNEL on the server.

I think I caught one typo (inline below).

Other than that, I managed to partially backport this to the 7.5p1
version running on my Fedora26 boxes, and verified that the server
side does indeed provide $SSH_TUNNEL, and I can then bring up my
server-end bridge quite nicely:

        ssh -f <server> \
                -o Tunnel=ethernet \
                'ip link set $SSH_TUNNEL up; ip link set $SSH_TUNNEL master br0'

That is awesome! I couldn't test the LocalCommand bits, since my
half-assed backport actually broke that functionality :)

I tried building git://anongit.mindrot.org/openssh.git, but it complains
about my OpenSSL version:

checking OpenSSL header version... 1010006f (OpenSSL 1.1.0f  25 May 2017)
checking OpenSSL library version... configure: error: OpenSSL >= 1.1.0 is not yet supported (have "1010006f (OpenSSL 1.1.0f-fips  25 May 2017)")

So, yes, with your patch I SHOULD be able to do something like:

        ssh -f <server> \
            -o Tunnel=ethernet -o PermitLocalCommand=yes \
            -o LocalCommand='ip link set %T up; ip link set %T master br0' \
            'ip link set $SSH_TUNNEL up; ip link set $SSH_TUNNEL master br0'

to fully add the tap interfaces to the local and remote bridges, respectively!

Are you planning on committing this upstream? If so, I'll try harder
to install the openssl-1.0 compatibility development headers and fully
test this -- it'd be the least I can do to support your effort!

(a backport against 7.5 would also be much appreciated, although I don't
want to push my luck... :)

Thanks much,
--Gabriel

> 
> Lightly tested.
> 
> ...
> 
> diff --git a/misc.c b/misc.c
> index 05950a47..1b976448 100644
> --- a/misc.c
> +++ b/misc.c
> @@ -724,16 +724,19 @@ read_keyfile_line(FILE *f, const char *filename, char *buf, size_t bufsz,
>  }
>  
>  int
> -tun_open(int tun, int mode)
> +tun_open(int tun, int mode, char **ifname)
>  {
>  #if defined(CUSTOM_SYS_TUN_OPEN)
> -	return (sys_tun_open(tun, mode));
> +	return (sys_tun_open(tun, mode, ifname));
>  #elif defined(SSH_TUN_OPENBSD)
>  	struct ifreq ifr;
>  	char name[100];
>  	int fd = -1, sock;
>  	const char *tunbase = "tun";
>  
> +	if (devname != NULL)
> +		*devname = NULL;

Did you mean "ifname" rather than "devname" here?

> +
>  	if (mode == SSH_TUNMODE_ETHERNET)
>  		tunbase = "tap";
>  
> @@ -780,6 +783,9 @@ tun_open(int tun, int mode)
>  		}
>  	}
>  
> +	if (ifname != NULL)
> +		*ifname = xstrdup(ifr.ifr_name);
> +
>  	close(sock);
>  	return fd;
>  
> diff --git a/misc.h b/misc.h
>
> ...


More information about the openssh-unix-dev mailing list