When you want to manage SSH connections across multiple servers in the cloud or on your home lab, you want to have an easy centralized approach. Or maybe you’re a company and want to manage SSH access for all your developers, engineers, including things like role-based access, two-factor authentication, single-sign-on, and so forth. And of course, you want all your SSH sessions to be secured, logged, and audited. Let me show you a very easy and powerful method to manage all your SSH connections with teleport. No matter if you’re planning to run this on your home lab or set up in a corporate environment.
Teleport is an open-source solution to manage SSH servers
I’ve found this software when I searched for an open-source SSH proxy solution that can be easily deployed in a containerized environment. If you know me, you know that I like to run almost everything containerized. Teleport is such an open-source software made by Gravitational that exists in a completely free community edition. It is rich-featured and supports two-factor authentication, access control, monitoring, auditing, and a web client for all your SSH connections. It can suit your home lab but it’s also targeted for enterprise environments. Companies that usually need to integrate existing external authentication methods and single-sign-on can also purchase an enterprise license.
It uses common industry standards for protocols and CA-pinning which is a good idea to secure access to all your SSH servers. But one of the best features for me is the ability to create a reverse tunnel for SSH servers that are behind a NAT firewall or behind a shared IPv4 tunnel. Because my ISP doesn’t provide me a real IPv4 address, this is very useful to me. It’s also a good way to connect to IoT devices that are often behind a NAT device.
Install the Auth and Proxy server
If you want to learn more about the architecture and the concept of teleport, you should have a look at the official documentation. I can’t cover all the details and deployment architectures in this short tutorial. But I will walk you step by step through the basics and we will also cover everything you need to know for a production environment.
First, we will need to install an authentication and proxy server. This will handle the whole authentication process for all nodes and clients. It also runs a proxy where we can connect to. You can connect to the proxy from a terminal client or via a web client. It also comes with other cool features, I will show you later. I’m running this in a cloud environment because I can easily access this server from anywhere and it’s flexible. But in theory, you could also run this in your home lab or on-premise.
I’m using docker-compose to deploy the teleport proxy and auth server, but you can also install this directly on Linux, without docker if you want. However, I like the containerized deployment because it offers me the most flexibility.
version: '2' services: configure: image: quay.io/gravitational/teleport:4.3 container_name: teleport-configure entrypoint: /bin/sh hostname: dev.the-digital-life.com command: -c "if [ ! -f /etc/teleport/teleport.yaml ]; then teleport configure > /etc/teleport/teleport.yaml; fi" volumes: - ./config:/etc/teleport teleport: image: quay.io/gravitational/teleport:4.3 container_name: teleport entrypoint: /bin/sh hostname: dev.the-digital-life.com command: -c "sleep 1 && /bin/dumb-init teleport start -c /etc/teleport/teleport.yaml" ports: - "3023:3023" - "3024:3024" - "3025:3025" - "3080:3080" volumes: - ./config:/etc/teleport - ./data:/var/lib/teleport depends_on: - configure
Before you start the container you should change the “hostname” of both containers and set this to the Fully-qualified domain name of your server. You can still change it later in the configuration file, but if you set this up right from the beginning it makes things a lot easier. Then start the docker container with the following command.
docker-compose up -d
When we start this compose file, it will automatically create a default configuration and obtains self-signed certificates. Let’s make some adjustments in the configuration file, which is located in <folder>/config/teleport.yaml
teleport: nodename: <your-fqdn> data_dir: /var/lib/teleport auth_token: <your-auth-token> auth_servers: - 127.0.0.1:3025 log: output: stderr severity: INFO ca_pin: sha256:ca-pin-hash-goes-here auth_service: enabled: "yes" listen_addr: 0.0.0.0:3025 public_addr: <your-fqdn>:3025 tokens: - proxy,node:<token> license_file: /path/to/license-if-using-teleport-enterprise.pem ssh_service: enabled: "yes" labels: db_role: master db_type: postgres commands: - name: hostname command: [/usr/bin/hostname] period: 1m0s - name: arch command: [/usr/bin/uname, -p] period: 1h0m0s proxy_service: enabled: "yes" listen_addr: 0.0.0.0:3023 public_addr: <your-fqdn> ssh_public_addr: <your-fqdn> web_listen_addr: 0.0.0.0:3080 tunnel_listen_addr: 0.0.0.0:3024
Make sure you add the “public_addr” and “ssh_public_addr” on the auth_service and proxy_service. Replace the <your-fqdn> with your FQDN of your teleport server or reverse-proxy/load-balancer.
You also should replace your ca_pin, you can obtain by executing the following command.
docker-compose exec teleport tctl status
After that restart your docker container with the following command.
docker-compose up -d --force-recreate
Add a load balancer or reverse-proxy to obtain trusted HTTPS certificates
At this point, I also want to add a reverse-proxy to obtain trusted HTTPS certificates. It’s very common to use a load-balancer within your cloud provider to do that. I’m using DigitalOcean as my cloud provider so I can easily add a load-balancer that obtain trusted letsencrypt certificates.
But if you don’t use DigitalOcean you can still set up a load balancer or a reverse-proxy yourself.
Don’t forget to add TCP load balancing rules for the port 3023, 3024, 3025!
How to manage teleport and connect our SSH servers
Now, we will create a user on the teleport auth server. Every teleport user should also map to a user that exists on your nodes. But you can also assign multiple mappings.
docker-compose exec teleport tctl users add teleport root,xcad,christian,vagrant
With this command, I will add a new user called “teleport” who can log in with the Linux users “root”, “xcad”, “christian”, and “vagrant” on the nodes.
This will create a registration token. With the registration token, we can now set up our credentials on the teleport server. Teleport enforces 2FA by default. Install a 2FA like Google Authentication or Authy on your smartphone and scan the QR-Code. Then you can simply enter the 2FA code that is generated on your smartphone.
Now you can simply connect to the docker node with the web interface by accessing https://<your-fqdn>:3080
Add additional SSH servers to teleport
To add another node to the proxy server, we need to download and run the teleport client on a server. But first, we need to create a new token on the auth server.
Docker-compose exec teleport tctl nodes add
We could now just execute this command on the node, once teleport is downloaded. But I prefer to add this to a static configuration file, that allows me to run the teleport as a systemd service. Download the latest version of teleport and install the package on your node. In this example, I download the .deb package and install it on an Ubuntu server.
root@teleport-node-1:~# wget https://get.gravitational.com/teleport_4.3.7_amd64.deb
I also create a new configuration file /etc/teleport.yaml and add the following values:
teleport: nodename: teleport-node-1 data_dir: /var/lib/teleport auth_token: <your-auth-token> auth_servers: - <your-fqdn>:3025 log: output: stderr severity: INFO ca_pin: <your-ca-pin-hash> auth_service: enabled: no ssh_service: enabled: yes proxy_service: enabled: no
Note: If your node doesn’t show up with the correct public IP address in your teleport server, you can manually enforce this by adding the attribute to the “teleport:” section in the configuration file.
Now we can simply start the teleport service with the command:
Sudo systemctl enable –now teleport
If everything works successfully, you should be able to see the new node in the teleport proxy server.
How to add SSH servers through a reverse tunnel to teleport
I also want to test the reverse tunnel for my home lab servers. The trick is to use a teleport reverse tunnel that establishes a connection from inside the network to the cloud server. With this solution, you’re able to connect all SSH servers behind a NAT.
To create a reverse tunnel, simply change the port of the auth server to 3080 in the /etc/teleport.yaml configuration file.
teleport: nodename: teleport-node-1 data_dir: /var/lib/teleport auth_token: <your-auth-token> auth_servers: - <your-fqdn>:3080 log: output: stderr severity: INFO ca_pin: <your-ca-pin-hash> auth_service: enabled: no ssh_service: enabled: yes proxy_service: enabled: no