Networking AWS

EasyTier 2.6.4 on AWS User Guide

| Product: EasyTier 2.6.4 on Ubuntu 24.04 on AWS

Overview

This guide covers launching and verifying EasyTier 2.6.4 on Ubuntu 24.04 from cloudimg on Amazon EC2. It is one version of the cloudimg Hardened WireGuard VPN & VPN, Proxy and Remote Access AMIs listing on AWS Marketplace; you pick it as the software version when you subscribe and launch. The other VPN, proxy and remote access servers in the listing are described on the listing's guide hub.

EasyTier is an open-source decentralized mesh VPN written in Rust. Every node is a peer: nodes that share a network name and network secret find each other, build encrypted point-to-point tunnels (over TCP or UDP, with NAT hole punching and relaying when a direct path is impossible) and form one flat private network. There is no central controller to run. On this image the EC2 instance is a ready-to-use, always-on node of a new private network that your laptops, servers and sites join.

EasyTier 2.6.4 is installed from the official release: cloudimg pins the checksums of the release archive and of the two binaries it installs (easytier-core, the node, and easytier-cli, its management tool). The build record and the LGPL source offer are in /usr/share/doc/easytier/BUILD-PROVENANCE.txt.

What is on the image:

  • EasyTier 2.6.4 (easytier.service): the mesh node, with mesh address 10.144.144.1 on interface et0 and the peer transport on port 11010, TCP and UDP
  • A network of its own: the network name and the network secret (the key that admits peers) are generated on your instance's first boot; no two instances share them
  • Private mode on: the node serves your network only and never relays anyone else's
  • Management on loopback, root only: the RPC portal easytier-cli talks to listens on 127.0.0.1:15888, and only root may connect to it
  • No metadata access from the mesh: nothing a mesh peer sends can reach the instance metadata service, even through a subnet proxy or exit node you enable later
  • Helpers: easytier-selftest (an end-to-end mesh test with a second node) and easytier-imds-guard (the metadata guard)

Default user: ubuntu · Architecture: x86_64 · Root volume: 8 GiB gp3

Security posture

  • No default secret. Any node that knows a network's name and secret can join it, so a shared or published secret would let strangers into your network. The image ships a configuration template with placeholders only; first boot generates a 40-character network secret and a network name on your instance, writes /etc/easytier/config.toml (readable only by root) and the credentials file /root/easytier-credentials.txt (readable only by root), and only then starts the node.
  • Private mode. Upstream EasyTier, by default, lets any EasyTier node that can reach port 11010 use the node as a relay for that node's own network, so a stranger's traffic would cross your instance. This image sets private_mode = true: connections from any other network are refused. A node that uses your network name with the wrong secret is refused too.
  • Off until you turn it on. No public peer, relay server, subnet proxy or exit node is configured. The in-mesh QUIC proxy endpoint (disable_quic_input) and UPnP port mapping (disable_upnp) are off. Mesh traffic is encrypted (enable_encryption = true).
  • The secret stays out of the logs. At its default log level EasyTier writes its whole configuration, network secret included, to the log when it starts. easytier.service runs it at --console-log-level warn, so warnings and errors are logged and the secret is not.
  • Management on loopback, root only. The RPC portal is bound to 127.0.0.1:15888 (EasyTier 2.6 ignores the configuration file's rpc_portal key, so the address is fixed in the unit), and a firewall rule refuses connections to it from any user but root. Run easytier-cli with sudo.
  • No SSRF to instance credentials, on both paths. easytier.service carries an IPAddressDeny rule for the metadata addresses (169.254.169.254, fd00:ec2::254, 168.63.129.16), which covers every connection the node opens for remote peers (a subnet proxy or exit node). Packets the kernel forwards from the mesh interface do not belong to the service, so an nftables table (cloudimg-easytier-guard.service) drops every forwarded packet to those addresses as well. cloudimg tested both with a second EasyTier node: a peer that routes 169.254.169.254 into the mesh, a subnet proxy deliberately covering it, and the same proxy forwarded by the kernel all get nothing. The AMI is registered IMDSv2 only.
  • Least privilege. EasyTier creates a network interface and routes, so it runs as root, bounded to the network capabilities (CAP_NET_ADMIN, CAP_NET_RAW, CAP_NET_BIND_SERVICE), with NoNewPrivileges, a read-only /usr, /boot and /etc, and no access to home directories.
  • Fails closed. easytier.service starts only after first boot has written the ready marker, only with the metadata guard loaded, and only after a check refuses a placeholder or short secret. If first boot cannot finish, the node stays stopped and the next boot starts over with a new identity.
  • Per-instance identity. SSH host keys and the machine ID are generated fresh on every instance.
  • What the node contacts. With no peers configured, the node only contacts STUN servers, to learn its own public address and NAT type for hole punching: upstream's defaults (txt:stun.easytier.cn, stun.miwifi.com, stun.chat.bilibili.com, stun.hitv.com, IPv6 txt:stun-v6.easytier.cn; a TCP hole punch uses upstream's TCP STUN list). A STUN server sees the node's public address and nothing else. Step 9 shows how to use your own.
  • Security notes. cargo audit of EasyTier 2.6.4's dependencies finds no reachable high-severity advisory in this configuration. The QUIC library (quinn-proto 0.11.12) has remote denial-of-service advisories (RUSTSEC-2026-0037, -0185, -0340); this image does not expose QUIC (no quic:// listener, the in-mesh QUIC proxy input off, private mode on). Do not add a quic:// listener until a fixed EasyTier release ships.

Prerequisites

  1. An AWS account and permission to launch EC2 instances
  2. An EC2 key pair in the Region you launch in
  3. A subnet with outbound internet access (a public subnet, or a private subnet with a NAT gateway), and a public IP address (or Elastic IP) if peers outside AWS will connect to this node

Recommended instance type: m5.large. EasyTier is light; traffic you relay through the node is what needs bandwidth.

Connecting to your instance

Version Operating system SSH user
EasyTier 2.6.4 on Ubuntu 24.04 Ubuntu 24.04 LTS ubuntu

Step 1: Launch the instance

Option A: AWS Marketplace console

  1. Open the cloudimg Hardened WireGuard VPN & VPN, Proxy and Remote Access AMIs listing on AWS Marketplace and choose View purchase options, then Subscribe. One subscription covers every version in the listing.
  2. Once the subscription is active, choose Launch your software.
  3. Choose One-click launch from AWS Marketplace (or Launch from EC2 Console for the full launch wizard). In Version, choose EasyTier 2.6.4 on Ubuntu 24.04, then choose your Region.
  4. Pick an instance type (m5.large recommended; the software charge is $0.04 per vCPU per hour) and your key pair.
  5. Security group: the listing's default group allows SSH (22) only. Restrict SSH to your own IP address. You open the mesh port to your peers in Step 5.
  6. Choose a subnet with internet access and a public IP, leave the metadata defaults (the image already requires IMDSv2), then choose Launch.

Option B: AWS CLI

Run this on your own workstation. It creates a security group that allows SSH from your management address and the EasyTier port from your peers, then launches the instance. Replace the AMI ID with the one shown for your Region on the Marketplace launch page, and the VPC, subnet, key pair and address ranges with your own:

SG=$(aws ec2 create-security-group --group-name easytier \
  --description "EasyTier mesh VPN node" --vpc-id vpc-0123456789abcdef0 \
  --query GroupId --output text)
aws ec2 authorize-security-group-ingress --group-id "$SG" --protocol tcp --port 22 --cidr <your-mgmt-cidr>
aws ec2 authorize-security-group-ingress --group-id "$SG" --protocol tcp --port 11010 --cidr <your-peer-cidr>
aws ec2 authorize-security-group-ingress --group-id "$SG" --protocol udp --port 11010 --cidr <your-peer-cidr>
aws ec2 run-instances \
  --image-id ami-0123456789abcdef0 \
  --instance-type m5.large \
  --key-name my-key-pair \
  --security-group-ids "$SG" \
  --subnet-id subnet-0123456789abcdef0 \
  --associate-public-ip-address \
  --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=easytier}]'

You do not need --metadata-options: the AMI already makes IMDSv2 required.

Step 2: Connect and read your network details

Connect as ubuntu with the key pair you chose:

ssh -i ~/.ssh/my-key-pair.pem ubuntu@<public-ip>

First boot finishes within a minute of launch. It generates the network name and secret, writes the configuration, loads the metadata guard and starts the node. The details are in /root/easytier-credentials.txt, readable only by root. This command shows everything except the secret:

sudo grep -v '^easytier.network_secret=' /root/easytier-credentials.txt
# EasyTier 2.6.4 - generated on first boot by easytier-firstboot.service.
# The network secret below admits peers into this instance's private mesh. It was generated on this instance
# and no other instance shares it. Keep this file private. To join another machine, install EasyTier on it
# and run it with the same network name and secret, pointing it at this node (see the guide):
#   https://www.cloudimg.co.uk/guides/easytier-2-6-4-on-ubuntu-24-04-aws/

easytier.network_name=cloudimg-16aa85de60b2
easytier.virtual_ipv4=10.144.144.1
easytier.node_endpoint=52.204.42.8:11010
easytier.private_ipv4=172.31.82.234
easytier.rpc_portal=127.0.0.1:15888
easytier.config=/etc/easytier/config.toml
easytier.self_test=sudo easytier-selftest

easytier.node_endpoint is the address your peers connect to (the instance's public IPv4; the private one if it has none). Your values differ. To print the secret when you set up a peer:

sudo grep '^easytier.network_secret=' /root/easytier-credentials.txt | cut -d= -f2-

Step 3: Confirm the node is running

The node and the metadata guard are active. The node listens on 11010 over TCP and UDP (IPv4 and IPv6) and its management portal on loopback only:

systemctl is-active easytier.service cloudimg-easytier-guard.service
/opt/easytier/easytier-core --version
sudo ss -Htulnp 'sport = :11010 or sport = :15888' | awk '{print $1, $5}'
active
active
easytier-core 2.6.4-8428a89d
udp 0.0.0.0:11010
udp [::]:11010
tcp 0.0.0.0:11010
tcp 127.0.0.1%lo:15888
tcp [::]:11010

easytier-cli shows the node itself (its mesh address, public address and NAT type as STUN sees them, and its listeners):

sudo /opt/easytier/easytier-cli node | grep -E 'Virtual IP|Public IPv4|UDP Stun Type|Listener'
| Virtual IP     | 10.144.144.1/24     |
| Public IPv4    | 52.204.42.8         |
| UDP Stun Type  | PortRestricted      |
| Listener 1     | tcp://0.0.0.0:11010 |
| Listener 2     | tcp://[::]:11010    |
| Listener 3     | udp://0.0.0.0:11010 |
| Listener 4     | udp://[::]:11010    |

Step 4: Run the self-test

The shipped self-test proves the mesh end to end without any machine of yours: it starts a second, short-lived EasyTier node in an isolated network namespace with this instance's network name and secret, checks that it joins over the encrypted tunnel, pings across the two mesh addresses in both directions, and checks that the test node cannot reach the instance metadata service through the mesh and that the node itself cannot reach it either. It prints no secret and cleans up after itself:

sudo easytier-selftest
ok: easytier.service is active (pid 5128)
ok: management RPC portal on 127.0.0.1:15888 only
ok: metadata guard loaded (forward drop for 169.254.169.254, 168.63.129.16, fd00:ec2::254)
ok: a test node joined over the encrypted tunnel; ping 10.144.144.1 <-> 10.144.144.250 answers in both directions
ok: both nodes list each other as peers (easytier-cli peer list)
ok: metadata: 169.254.169.254 is unreachable from a mesh peer through this node
ok: metadata: 169.254.169.254 is unreachable from inside easytier.service
SELFTEST_OK

Step 5: Let your peers reach the node

Peers outside the VPC connect to easytier.node_endpoint on port 11010. Open TCP and UDP 11010 in the instance's security group to your peers' addresses (your office, your other clouds), never to 0.0.0.0/0 unless your peers have no fixed address. The network secret is what keeps strangers out, and private mode refuses other networks, but a narrow rule keeps scanners away from the port:

aws ec2 authorize-security-group-ingress --group-id <your-sg> --protocol tcp --port 11010 --cidr <your-peer-cidr>
aws ec2 authorize-security-group-ingress --group-id <your-sg> --protocol udp --port 11010 --cidr <your-peer-cidr>

If you would rather open no inbound port at all, let the node connect out to a peer that has one instead (Step 8).

Step 6: Join another machine

Install EasyTier on the machine you want to add (downloads for Linux, Windows, macOS, Android and others are on the EasyTier releases page; the desktop and mobile apps take the same network name, secret and peer address). On a Linux machine, use a configuration file rather than putting the secret on the command line. Give every node its own mesh address:

curl -fsSLO https://github.com/EasyTier/EasyTier/releases/download/v2.6.4/easytier-linux-x86_64-v2.6.4.zip
unzip easytier-linux-x86_64-v2.6.4.zip
sudo install -d -m 0700 /etc/easytier
sudo tee /etc/easytier/config.toml >/dev/null <<'EOF'
ipv4 = "10.144.144.2"
[network_identity]
network_name = "<network-name>"
network_secret = "<network-secret>"
[[peer]]
uri = "tcp://<node-endpoint>"
[flags]
private_mode = true
EOF
sudo chmod 600 /etc/easytier/config.toml
sudo ./easytier-linux-x86_64/easytier-core -c /etc/easytier/config.toml --console-log-level warn

Replace <network-name>, <network-secret> and <node-endpoint> with the values from Step 2. Use udp:// instead of tcp:// if you prefer the UDP transport. Within a few seconds the two machines reach each other on 10.144.144.1 and 10.144.144.2; once a third machine joins, the nodes connect to each other directly where they can (hole punching) and relay through this node where they cannot.

Step 7: Check peers and routes

On the instance, the peer and route tables list every node of your network (on a new instance only the node itself appears):

sudo /opt/easytier/easytier-cli peer list
sudo /opt/easytier/easytier-cli route list | cut -c1-110
| ipv4            | hostname         | cost  | lat(ms) | loss | rx | tx | tunnel | NAT            | version        |
|-----------------|------------------|-------|---------|------|----|----|--------|----------------|----------------|
| 10.144.144.1/24 | ip-172-31-82-234 | Local | -       | -    | -  | -  | -      | PortRestricted | 2.6.4-8428a89d |
| ipv4            | hostname         | proxy_cidrs | next_hop_ipv4 | next_hop_hostname | next_hop_lat | path_len |
|-----------------|------------------|-------------|---------------|-------------------|--------------|----------|
| 10.144.144.1/24 | ip-172-31-82-234 |             | -             | Local             | 0            | 0        |

Only root may use the management portal; any other user is refused:

sudo -u nobody /opt/easytier/easytier-cli node >/dev/null 2>&1 || echo "refused for a non-root user"
refused for a non-root user

Step 8: Configuration changes

The node's configuration is /etc/easytier/config.toml (root only). Edit it, then restart the node; the start-up check refuses a configuration without a real network identity:

sudo nano /etc/easytier/config.toml
sudo systemctl restart easytier

To have the node connect out to a peer that accepts connections (so this instance needs no inbound port), add a [[peer]] section, for example uri = "tcp://<peer-public-ip>:11010", and restart.

Step 9: Subnet proxy, exit node and STUN servers (opt in)

These are off on this image; enable them deliberately.

  • Subnet proxy: let your peers reach addresses in your VPC (or another network this instance can reach) through the mesh. Add a [[proxy_network]] section with cidr = "<subnet-cidr>", restart, and allow this instance in the security groups of the targets. Peers learn the route automatically.
  • Exit node: set enable_exit_node = true in [flags] and restart; a peer then uses it with exit_nodes = ["10.144.144.1"] in its own configuration.
  • Your own STUN servers: add a top-level line such as stun_servers = ["stun.l.google.com:19302"] (and stun_servers_v6 for IPv6) before the first [section], and restart.

Even with a subnet proxy or exit node on, and with IP forwarding enabled, no peer can reach the instance metadata service through the node (Step 10).

Step 10: Metadata access is blocked

The node cannot reach the metadata service, and the guard drops every packet the kernel would forward to it. Its counters show any attempt:

systemctl show -p IPAddressDeny easytier.service
sudo easytier-imds-guard show
IPAddressDeny=fd00:ec2::254/128 169.254.169.254/32 168.63.129.16/32
table inet cloudimg_easytier {
    chain forward {
        type filter hook forward priority filter - 10; policy accept;
        ip daddr { 168.63.129.16, 169.254.169.254 } counter packets 0 bytes 0 drop
        ip6 daddr fd00:ec2::254 counter packets 0 bytes 0 drop
    }

    chain output {
        type filter hook output priority filter - 10; policy accept;
        oifname "lo" tcp dport 15888 meta skuid != 0 counter packets 0 bytes 0 reject with tcp reset
    }
}

The guard is re-applied when nftables.service restarts, and easytier.service will not run without it.

Step 11: How the fail-closed start works

easytier.service runs only when first boot's ready marker exists and only together with the guard, and every start runs a check as root first. The files that hold the network secret are readable only by root:

systemctl cat easytier.service | grep -E '^(ConditionPathExists|Requires|ExecStartPre|ExecStart|CapabilityBoundingSet)='
sudo stat -c '%a %U:%G %n' /root/easytier-credentials.txt /etc/easytier /etc/easytier/config.toml
sudo sed -n '/^\[flags\]/,$p' /etc/easytier/config.toml | grep -v '^#'
Requires=cloudimg-easytier-guard.service
ConditionPathExists=/var/lib/cloudimg/easytier-ready
ExecStartPre=+/usr/local/sbin/easytier-preflight
ExecStart=/opt/easytier/easytier-core -c /etc/easytier/config.toml --rpc-portal 127.0.0.1:15888 --console-log-level warn
CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_RAW CAP_NET_BIND_SERVICE
600 root:root /root/easytier-credentials.txt
700 root:root /etc/easytier
600 root:root /etc/easytier/config.toml
[flags]
dev_name = "et0"
default_protocol = "tcp"
enable_encryption = true
enable_ipv6 = true
private_mode = true
disable_quic_input = true
disable_upnp = true
enable_exit_node = false
proxy_forward_by_system = false

Step 12: Generate a new network identity

To replace the network name and secret (for example after a peer machine is lost), run first boot again. It mints a new identity, rewrites the configuration and the credentials file and restarts the node; every peer then needs the new values:

sudo systemctl stop easytier.service
sudo rm -f /var/lib/cloudimg/easytier-firstboot.done /var/lib/cloudimg/easytier-ready
sudo systemctl restart easytier-firstboot.service
systemctl is-active easytier.service
sudo grep '^easytier.network_name=' /root/easytier-credentials.txt | cut -c1-31
active
easytier.network_name=cloudimg-

Step 13: Logs

journalctl -u easytier shows warnings and errors. To troubleshoot, you can run the node at --console-log-level info (in a drop-in for easytier.service), but at that level EasyTier writes its whole configuration, network secret included, into the journal when it starts: switch back to warn afterwards and generate a new identity (Step 12) if anyone else can read the journal.

Step 14: Security recommendations

  • Keep SSH open only to your management addresses, and port 11010 only to your peers where you can.
  • Treat the network secret like a password: share it only with machines you control, keep peer configuration files at mode 0600, and generate a new identity (Step 12) if one is exposed.
  • Keep private mode on unless you deliberately want to run a public relay.
  • Give every node its own mesh address; use EasyTier's ACL options if some peers must not reach others.
  • Leave unattended security upgrades on. EasyTier is two binaries in /opt/easytier; cloudimg ships updated versions as new versions of this listing.

Support and licensing

EasyTier is open-source software by the EasyTier project and contributors, distributed under the GNU Lesser General Public License v3.0 (LGPL-3.0). The licence and cloudimg's build record, with the source offer for the unmodified upstream 2.6.4 release (also available from support@cloudimg.co.uk), are in /usr/share/doc/easytier/. cloudimg provides the packaging, the per-instance network identity, private mode and the other secure defaults, the root-only management portal, the metadata guard, the fail-closed start, the self-test and 24/7 support.

cloudimg is not affiliated with or endorsed by the EasyTier project. EasyTier is used here only to identify the software. STUN server names shown are those of their operators.

For help with deployment or configuration, email support@cloudimg.co.uk or visit cloudimg support.