Remote Kerberos authentication through an SSH tunnel

In the previous post, I’ve blogged about how to remotely log in to a machine via Kerberos authentication, but the Kerberos server had to be reachable from the network, which in many cases means having to connect to a workplace’s VPN. In this post, I’ll describe how to do the same, but via an SSH tunnel, instead of VPN.

To connect to a Kerberos server that is within a workplace’s internal network, one has to use either VPN or an SSH tunnel. To create an SSH tunnel, the workplace needs to have an SSH gateway server that is accessible from the outside. To connect to the Kerberos server via SSH tunneling, we’ll first replace the Kerberos authentication server URLs in the Kerberos config with localhost and a local port, and then route that port through an SSH tunnel that we will open.

First, we’ll check the [realms] section of our /etc/krb5.conf for the relevant Kerberos server URLs:

kdc = kdc.workplace.ac.uk
admin_server = kadm.workplace.ac.uk

Replace these two servers with the following:

kdc = localhost:6200
admin_server = localhost:6200

Local port can be chosen to our liking, we’ll choose 6200 here.

Next, we’ll open an SSH tunnel that will forward that local port 6200 through the tunnel to the destination kdc.workplace.ac.uk at port 88 (the Kerberos default port):

$ ssh -L 6200:kdc.workplace.ac.uk:88 user@ssh.workplace.ac.uk

We’ll have to authenticate via password or SSH public keys here once.

After the tunnel is open, we can run kinit user@WORKPLACE.AC.UK as before to obtain a Kerberos ticket! The kinit traffic will go to localhost:6200, which will subsequently be routed through our tunnel to kdc.workplace.ac.uk:88.

Now we can connect to the workplace’s internal machines and this Kerberos ticket will be used for authenticating automatically:

$ ssh -J user@ssh.workplace.ac.uk user@server.workplace.ac.uk

Remark 1: ssh‘s -J option requires a somewhat-recent ssh version. The one in Ubuntu 18.04 works fine, while the one in 16.04 looks like it’s too old. -J is just a short-hand for ssh to do a proxy-jump. On older versions, one can just connect to ssh.workplace.ac.uk first and then manually “hop” to server.workplace.ac.uk. -J saves this extra step though.

Remark 2: Kerberos uses UDP by default, while SSH tunnels forward only TCP traffic. There are answers to questions like this suggesting that either the UDP packets need to be transformed to TCP and then back, or to prefix the kdc and admin_server URLs in /etc/krb5.conf with /tcp like so:

kdc = tcp/localhost:6200
admin_server = tcp/localhost:6200

However, on Ubuntu (or WSL), this causes kinit to actually break and not being able to make a connection. There is a krb5.conf manpage on FreeBSD.org that suggests that this syntax exists:

kdc = [service/]host[:port] ... The optional service specifies over what medium the kdc should be contacted. Possible services are "udp", "tcp", and "http".

But it looks like this option is only available on FreeBSD though (and potentially on macOS), where it may or may not be needed. On Ubuntu / WSL, you may not use tcp/ in the config, and kinit will then automatically attempt a connection via UDP first (which will silently fail), and then switch to TCP and successfully connect through the tunnel.

I hope this was helpful!

Leave a comment