{"id":3643,"date":"2022-02-02T00:08:00","date_gmt":"2022-02-01T16:08:00","guid":{"rendered":"https:\/\/tzlee.com\/blog\/?p=3643"},"modified":"2022-02-08T16:04:37","modified_gmt":"2022-02-08T08:04:37","slug":"gravitational-teleport-as-a-bastion-host","status":"publish","type":"post","link":"https:\/\/tzlee.com\/blog\/2022\/02\/gravitational-teleport-as-a-bastion-host\/","title":{"rendered":"Gravitational Teleport as a Bastion Host"},"content":{"rendered":"\n<p>Gravitiational <a rel=\"noreferrer noopener\" href=\"https:\/\/goteleport.com\/\" data-type=\"URL\" data-id=\"https:\/\/goteleport.com\/\" target=\"_blank\">Teleport<\/a> 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.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"introduction\">Introduction<\/h2>\n\n\n\n<p>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 &#8220;bastion host&#8221;.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"components\">Components<\/h2>\n\n\n\n<p>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:<\/p>\n\n\n\n<figure class=\"wp-block-table is-style-regular\"><table class=\"has-fixed-layout\"><thead><tr><th>Service<\/th><th>Ports<\/th><\/tr><\/thead><tbody><tr><td><strong>Auth<\/strong><br \/><br \/>Authentication service to authenticate Clients and Nodes, and is also the Certificate Authority (CA) for the Teleport Cluster<\/td><td>3025 (Restricted access from Nodes only)<\/td><\/tr><tr><td><strong>Proxy<\/strong><br \/><br \/>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.<\/td><td>443 (HTTPS, can be public to Clients, should also be reachable by Nodes)<br \/><br \/>3023 (SSH Proxy, can be public to Clients)<br \/><br \/>3024 (SSH Reverse Proxy, restricted access from Nodes only)<\/td><\/tr><tr><td><strong>Node<\/strong><br \/><br \/>Provides SSH access to the system.<\/td><td>3022 (SSH, restricted access from Proxy only)<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>A Teleport &#8220;Server&#8221; only requires two components &#8211; Proxy and Auth, although a Node usually runs on the Server as well.<\/p>\n\n\n\n<p>The Nodes (<em>&#8220;Protected Resource&#8221;<\/em>) would only need to run the Node component.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"server-setup\">Server setup<\/h2>\n\n\n\n<p>In the example below, I am using an Amazon Linux 2 instance. You can refer to the <a href=\"https:\/\/goteleport.com\/docs\/installation\/\" target=\"_blank\" rel=\"noreferrer noopener\">installation docs<\/a> for other distros.<\/p>\n\n\n\n<p>Pre-requisites:<\/p>\n\n\n\n<ol class=\"wp-block-list\"><li>Set up an instance with a public IP address<\/li><li>Set up a DNS hostname that resolves to the public IP address correctly (this is required for LetsEncrypt)<\/li><li>Ensure the following TCP ports are open\/allowed<ol><li>Inbound, TCP 443, from public (required for LetsEncrypt)<\/li><li>Inbound, TCP 3023, from Clients<\/li><li>Inbound, TCP 3024, from Nodes<\/li><li>Inbound, TCP 3025, from Nodes (you can omit if you use reverse tunnel for Nodes behind firewall)<\/li><li>Outbound, TCP 3022, to Nodes<\/li><\/ol><\/li><\/ol>\n\n\n\n<p>Install Teleport:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo yum-config-manager --add-repo https:\/\/rpm.releases.teleport.dev\/teleport.repo\nsudo yum install teleport<\/code><\/pre>\n\n\n\n<p>Configure Teleport; replace your email and DNS hostname:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo teleport configure \\\n  --acme --acme-email=&lt;your.email@fqdn.here&gt; \\\n  --cluster-name=&lt;your.dns.hostname.here&gt; \\\n  -o file<\/code><\/pre>\n\n\n\n<p>At this point, you should realise that the configuration file is <code>\/etc\/teleport.yaml<\/code>. This file controls how and what component Teleport runs. <\/p>\n\n\n\n<p>Start Teleport in foreground to test\/debug first:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo teleport start<\/code><\/pre>\n\n\n\n<p>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:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo systemctl start teleport\nsudo systemctl enable teleport<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"user-management\">User management<\/h2>\n\n\n\n<p>When Teleport first starts, there are no user accounts provisioned. Add the first user:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo tctl users add --roles=access,editor --logins=root &lt;username&gt;<\/code><\/pre>\n\n\n\n<p>(This is your first interaction with the <code>tctl<\/code> command. The <code>tctl<\/code> command is the CLI admin tool for the Auth service. Type <code>tctl<\/code> to see other commands available.)<\/p>\n\n\n\n<p>In the example above, the user is given the <code>access<\/code> and <code>editor<\/code> roles to Teleport, and can login as the Linux <code>root<\/code> user to Nodes.<\/p>\n\n\n\n<p>To see what roles are available:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo tctl get roles<\/code><\/pre>\n\n\n\n<p>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.<\/p>\n\n\n\n<p>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.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"node-setup\">Node setup<\/h2>\n\n\n\n<p>In the example below, I am using an Ubuntu instance. You can refer to the&nbsp;<a rel=\"noreferrer noopener\" href=\"https:\/\/goteleport.com\/docs\/installation\/\" target=\"_blank\">installation docs<\/a>&nbsp;for other distros.<\/p>\n\n\n\n<p>Pre-requisites:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Ensure the following TCP ports are open\/allowed<ul><li>Inbound, TCP 3022, from Proxy<\/li><li>Outbound, TCP 443 and 3024, to Proxy<\/li><\/ul><\/li><\/ul>\n\n\n\n<p>Install Teleport:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>curl https:\/\/deb.releases.teleport.dev\/teleport-pubkey.asc | sudo apt-key add -\nsudo add-apt-repository 'deb https:\/\/deb.releases.teleport.dev\/ stable main'\nsudo apt-get update &amp;&amp; apt-get install teleport<\/code><\/pre>\n\n\n\n<p>From the bastion host (Server), generate a temporary token used to join a node:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo tctl tokens add --type=node --ttl=5m\nsudo tctl tokens ls # View tokens and expiry<\/code><\/pre>\n\n\n\n<p>The&nbsp;<code>--ttl=5m<\/code>&nbsp;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.<\/p>\n\n\n\n<p>Copy the output from the&nbsp;<code>tctl tokens add<\/code>&nbsp;command and run it on the Node to join:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo teleport start \\\n  --roles=node \\\n  --token=xxxx \\\n  --ca-pin=sha256:xxxx \\\n  --auth-server=your.dns.hostname.here:443<\/code><\/pre>\n\n\n\n<p>Note: If you change <code>auth-server<\/code> from the default port <code>3025<\/code> to port <code>443<\/code>, the Node will join via reverse tunnel.<\/p>\n\n\n\n<p>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.<\/p>\n\n\n\n<p>Create a file&nbsp;<code>\/etc\/teleport.yaml<\/code>&nbsp;on the node; replace&nbsp;<code>nodename<\/code>&nbsp;and&nbsp;<code>ca_pin<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>teleport:\n  nodename: &lt;your node name here; does not need to be a fqdn&gt;\n  ca_pin: \"sha256:xxxx\"\n  auth_servers:\n    - your.dns.hostname.here\n\nssh_service:\n  enabled: true\nauth_service:\n  enabled: false\nproxy_service:\n  enabled: false<\/code><\/pre>\n\n\n\n<p>Fix permissions to ensure that only root can access <code>\/etc\/teleport.yaml<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo chown root:root \/etc\/teleport.yaml\nsudo chmod 0600 \/etc\/teleport.yaml<\/code><\/pre>\n\n\n\n<p>Now, start the Teleport service and test if you are able to reach via Server&#8217;s Web UI:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo systemctl start teleport\nsudo systemctl enable teleport<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"access-control\">Access control<\/h2>\n\n\n\n<p>Control of access privileges is dependent upon the individual Node&#8217;s provision of the login user.<\/p>\n\n\n\n<p>For example, if I had the following users on my Nodes:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Linux Login<\/th><th>Node A<\/th><th>Node B<\/th><th>Node C<\/th><\/tr><\/thead><tbody><tr><td>engineer<\/td><td>Can <code>sudo<\/code><\/td><td>Can <code>sudo<\/code><\/td><td>Can <code>sudo<\/code><\/td><\/tr><tr><td>developer<\/td><td>Can only view logs<\/td><td>Can <code>sudo<\/code><\/td><td>(No account)<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>&#8230; and I provision the following users, the resultant access would be:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Teleport User<\/th><th>Can login as<\/th><th>Result of access<\/th><\/tr><\/thead><tbody><tr><td>user1<\/td><td>engineer<\/td><td>Can login to all Nodes and run <code>sudo<\/code><\/td><\/tr><tr><td>user2<\/td><td>developer<\/td><td>Can view logs on Node A<br \/>Can <code>sudo<\/code> on Node B<br \/>Can&#8217;t login to Node C<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>Note that the provisioned user on the Node does not need to have a password or SSH key, but must have a valid shell.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>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&#8230; <a class=\"more-link\" href=\"https:\/\/tzlee.com\/blog\/2022\/02\/gravitational-teleport-as-a-bastion-host\/\">Continue Reading &rarr;<\/a><\/p>\n","protected":false},"author":2,"featured_media":3647,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[8],"tags":[],"class_list":["post-3643","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-tech"],"jetpack_featured_media_url":"https:\/\/tzlee.com\/blog\/wp-content\/uploads\/2022\/02\/68747470733a2f2f676f74656c65706f72742e636f6d2f626c6f672f696d616765732f323032302f6772617669746174696f6e616c2d69732d74656c65706f72742d6865616465722e706e67.png","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/tzlee.com\/blog\/wp-json\/wp\/v2\/posts\/3643","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/tzlee.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/tzlee.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/tzlee.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/tzlee.com\/blog\/wp-json\/wp\/v2\/comments?post=3643"}],"version-history":[{"count":25,"href":"https:\/\/tzlee.com\/blog\/wp-json\/wp\/v2\/posts\/3643\/revisions"}],"predecessor-version":[{"id":3673,"href":"https:\/\/tzlee.com\/blog\/wp-json\/wp\/v2\/posts\/3643\/revisions\/3673"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/tzlee.com\/blog\/wp-json\/wp\/v2\/media\/3647"}],"wp:attachment":[{"href":"https:\/\/tzlee.com\/blog\/wp-json\/wp\/v2\/media?parent=3643"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/tzlee.com\/blog\/wp-json\/wp\/v2\/categories?post=3643"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/tzlee.com\/blog\/wp-json\/wp\/v2\/tags?post=3643"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}