Gravitiational Teleport is a pretty neat and lightweight open-source software that works great as a bastion host. However, some parts the documentation can be a bit vague for a first-time user so this blog entry serves as a reference material for myself, and hopefully it is also helpful to you.
Introduction
Teleport is a great way to control access into a network of restricted systems. It can be used as a single-point-of-entry, or commonly known as a “bastion host”.
Components
The same Teleport software is installed on every system, i.e. the server and the client installs the same package/binary. The software package contains the following components:
Service | Ports |
---|---|
Auth Authentication service to authenticate Clients and Nodes, and is also the Certificate Authority (CA) for the Teleport Cluster | 3025 (Restricted access from Nodes only) |
Proxy Web UI for public users (Clients). Tunnels SSH from Clients to Nodes. Also allows Nodes to create a reverse SSH tunnel through it for Client connections. | 443 (HTTPS, can be public to Clients, should also be reachable by Nodes) 3023 (SSH Proxy, can be public to Clients) 3024 (SSH Reverse Proxy, restricted access from Nodes only) |
Node Provides SSH access to the system. | 3022 (SSH, restricted access from Proxy only) |
A Teleport “Server” only requires two components – Proxy and Auth, although a Node usually runs on the Server as well.
The Nodes (“Protected Resource”) would only need to run the Node component.
Server setup
In the example below, I am using an Amazon Linux 2 instance. You can refer to the installation docs for other distros.
Pre-requisites:
- Set up an instance with a public IP address
- Set up a DNS hostname that resolves to the public IP address correctly (this is required for LetsEncrypt)
- Ensure the following TCP ports are open/allowed
- Inbound, TCP 443, from public (required for LetsEncrypt)
- Inbound, TCP 3023, from Clients
- Inbound, TCP 3024, from Nodes
- Inbound, TCP 3025, from Nodes (you can omit if you use reverse tunnel for Nodes behind firewall)
- Outbound, TCP 3022, to Nodes
Install Teleport:
sudo yum-config-manager --add-repo https://rpm.releases.teleport.dev/teleport.repo
sudo yum install teleport
Configure Teleport; replace your email and DNS hostname:
sudo teleport configure \
--acme --acme-email=<your.email@fqdn.here> \
--cluster-name=<your.dns.hostname.here> \
-o file
At this point, you should realise that the configuration file is /etc/teleport.yaml
. This file controls how and what component Teleport runs.
Start Teleport in foreground to test/debug first:
sudo teleport start
If all goes well, you should be able to reach the web interface at HTTPS port 443. Hit CTRL+C to stop, then start it as a service:
sudo systemctl start teleport
sudo systemctl enable teleport
User management
When Teleport first starts, there are no user accounts provisioned. Add the first user:
sudo tctl users add --roles=access,editor --logins=root <username>
(This is your first interaction with the tctl
command. The tctl
command is the CLI admin tool for the Auth service. Type tctl
to see other commands available.)
In the example above, the user is given the access
and editor
roles to Teleport, and can login as the Linux root
user to Nodes.
To see what roles are available:
sudo tctl get roles
Once the user is added, a sign up URL is provided. Send it to the user to set up his/her Teleport account, including registering an OTP. OTP is mandatory.
Note that Teleport does not create the logins on the Nodes. If the login does not exist, an attempt by the user to access the Node will simply fail.
Node setup
In the example below, I am using an Ubuntu instance. You can refer to the installation docs for other distros.
Pre-requisites:
- Ensure the following TCP ports are open/allowed
- Inbound, TCP 3022, from Proxy
- Outbound, TCP 443 and 3024, to Proxy
Install Teleport:
curl https://deb.releases.teleport.dev/teleport-pubkey.asc | sudo apt-key add -
sudo add-apt-repository 'deb https://deb.releases.teleport.dev/ stable main'
sudo apt-get update && apt-get install teleport
From the bastion host (Server), generate a temporary token used to join a node:
sudo tctl tokens add --type=node --ttl=5m
sudo tctl tokens ls # View tokens and expiry
The --ttl=5m
option sets a short 5 minute expiry for the token. Tokens are one-time-use only, so after a server has used the token, it should either expire or we should remove it.
Copy the output from the tctl tokens add
command and run it on the Node to join:
sudo teleport start \
--roles=node \
--token=xxxx \
--ca-pin=sha256:xxxx \
--auth-server=your.dns.hostname.here:443
Note: If you change auth-server
from the default port 3025
to port 443
, the Node will join via reverse tunnel.
The above command starts Teleport in the foreground for debug/testing. If Teleport registers successfully, you should see it appear on the Web UI. Hit CTRL+C to shut down Teleport on the Node.
Create a file /etc/teleport.yaml
on the node; replace nodename
and ca_pin
:
teleport:
nodename: <your node name here; does not need to be a fqdn>
ca_pin: "sha256:xxxx"
auth_servers:
- your.dns.hostname.here
ssh_service:
enabled: true
auth_service:
enabled: false
proxy_service:
enabled: false
Fix permissions to ensure that only root can access /etc/teleport.yaml
:
sudo chown root:root /etc/teleport.yaml
sudo chmod 0600 /etc/teleport.yaml
Now, start the Teleport service and test if you are able to reach via Server’s Web UI:
sudo systemctl start teleport
sudo systemctl enable teleport
Access control
Control of access privileges is dependent upon the individual Node’s provision of the login user.
For example, if I had the following users on my Nodes:
Linux Login | Node A | Node B | Node C |
---|---|---|---|
engineer | Can sudo | Can sudo | Can sudo |
developer | Can only view logs | Can sudo | (No account) |
… and I provision the following users, the resultant access would be:
Teleport User | Can login as | Result of access |
---|---|---|
user1 | engineer | Can login to all Nodes and run sudo |
user2 | developer | Can view logs on Node A Can sudo on Node BCan’t login to Node C |
Note that the provisioned user on the Node does not need to have a password or SSH key, but must have a valid shell.