Introduction
Crusoe VPC Firewall Rules are stateful: once a VM's outbound connection is allowed, the firewall remembers the session and permits the return traffic automatically, without a separate ingress rule.
Every rule is defined by a five-tuple — action, direction, protocol, source, and destination — and by default all traffic is implicitly denied unless a rule explicitly allows it.
The default VPC network, default-vpc-network, ships with two default egress rules — default-allow-icmp-egress and default-allow-tcp-udp-egress — that allow any VM in it to reach the Internet over any port. That's convenient for getting started, but it's rarely what you want in production: an unrestricted egress rule means a compromised VM can talk to anything on the Internet.
Removing the default rules fixes that, but it also fully isolates the VM until you add rules for the specific traffic it actually needs.
This article walks through scoping egress access down to just the ports your workload requires, and how to find those ports when they aren't documented.
⚠️ Warning: Deleting the default egress rules without replacing them will leave the VM with no outbound connectivity at all. Add replacement rules for the traffic you need before or immediately after removing the defaults.
Prerequisites
- VPC Network Configured
- At Least One VM Deployed in the VPC (Examples in This Article Use a VPC Named
fwrules-demo) - Crusoe CLI Installed and Authenticated (Rule-Creation Steps Only)
- Root or
sudoAccess on the VM (Packet-Capture Steps Only)
ℹ️ Note: The default egress rules described below are applied automatically only to the true default VPC network. Custom VPC networks (like
fwrules-demo, used for the examples here) are not created with any default firewall rules — on a custom VPC there is nothing to remove, and you start from the implicit deny described in Step 2.
Instructions
Step 1: Review and Remove the Default Egress Rules
If your VMs sit in the default VPC network, two rules already allow any connection from those VMs to the Internet over TCP, UDP, or ICMP:
| Name | Protocols | Src Ports | Src Resources | Dst Ports | Dst Resources |
|---|---|---|---|---|---|
default-allow-icmp-egress |
icmp | — | default-vpc-network |
— | 0.0.0.0/0 |
default-allow-tcp-udp-egress |
tcp, udp | * |
default-vpc-network |
* |
0.0.0.0/0 |
These rules allow any interaction with the Internet on any port. Depending on your workload, you'll want to remove them and open only the specific ports and protocols your applications actually need.
List the rules on your VPC network to get their IDs, then delete the two defaults:
crusoe networking vpc-firewall-rules list --project-id <PROJECT_ID> crusoe networking vpc-firewall-rules delete <RULE_ID>
The remaining steps build the replacement rules back up, one protocol at a time. If you're working in a custom VPC network such as fwrules-demo, there are no default rules to delete — skip straight to Step 2.
Step 2: Allow Basic Internet Communication
HTTP(S) relies on TCP ports 80 and 443. Create a rule to allow egress on those ports:
crusoe networking vpc-firewall-rules create \ --name fwrules-internet-egress \ --action ALLOW \ --direction EGRESS \ --protocols tcp \ --source-ports "*" \ --sources <YOUR_VM_SOURCE_OR_TAG> \ --destination-ports 80,443 \ --destinations 0.0.0.0/0 \ --vpc-network-id <YOUR_VPC_NETWORK_ID>
That rule alone won't give you working connectivity, because resolving hostnames to IPs requires DNS.
DNS primarily uses UDP port 53. TCP is also used for DNSSEC and for servers that fall back to TCP on large responses, so it's safe to open both:
crusoe networking vpc-firewall-rules create \ --name fwrules-dns-egress \ --action ALLOW \ --direction EGRESS \ --protocols tcp,udp \ --source-ports "*" \ --sources <YOUR_VM_SOURCE_OR_TAG> \ --destination-ports 53 \ --destinations 0.0.0.0/0 \ --vpc-network-id <YOUR_VPC_NETWORK_ID>
With both rules created, the VPC firewall now has:
| Name | Protocols | Src Ports | Src Resources | Dst Ports | Dst Resources |
|---|---|---|---|---|---|
fwrules-internet-egress |
tcp | * |
fwrules-demo |
80, 443 | 0.0.0.0/0 |
fwrules-dns-egress |
tcp, udp | * |
fwrules-demo |
53 | 0.0.0.0/0 |
With both rules in place, the VM has basic browsing and connectivity:
ubuntu@vm-example:~$ curl www.crusoe.ai <html> <head><title>301 Moved Permanently</title></head> <body> <center><h1>301 Moved Permanently</h1></center> <hr><center>openresty</center> </body> </html>
Step 3: Open Ports for Other Common Protocols
Depending on what's running on the VM, you'll likely need additional ports:
| Protocol / App | Protocol(s) to Open | Port(s) |
|---|---|---|
| ICMP (ping, traceroute) | icmp | — |
| NTP | udp | 123 |
| FTP | tcp | 20, 21 |
| SSH, SFTP, SCP | tcp | 22 |
| Telnet | tcp | 23 |
| OpenVPN | tcp | 443 |
| OpenVPN | udp | 1194 |
ℹ️ Note: Crusoe blocks outbound SMTP on TCP ports 25, 465, and 2525 by default, regardless of firewall rules, for anti-spam reasons. If your workload sends email, use SMTP submission on port 587 or an HTTPS-based email API instead.
Step 4: Find Which Port an Application Needs
Because of the implicit "deny all," traffic on a port you haven't opened simply won't leave the VM — and that port isn't always documented. To find it, capture the traffic with a network sniffer and read the destination port off the wire.
tcpdump is installed by default on Ubuntu, but it can't identify retransmissions. tshark (Wireshark's CLI) can. If you can install it:
sudo apt-get update sudo apt install tshark -y
If tshark can't be installed, use the offline capture method described below instead.
Finding a Blocked TCP Port
TCP's 3-way handshake means a blocked port causes the initial SYN packet to be retransmitted, and that retransmission is what reveals the port in use.
- Open two consoles: one to test, one to capture.
- In Console 1, capture retransmissions:
sudo tshark -Y "tcp.analysis.retransmission"
- In Console 2, run the application or command you're troubleshooting. This example uses telnet to Google's DNS server:
telnet 8.8.8.8
- Console 2 hangs on the connection attempt:
Trying 8.8.8.8...
- Console 1 shows the retransmitted SYN packets, including the destination port:
3063 81.534104266 192.168.0.242 → 8.8.8.8 TCP 66 [TCP Retransmission] 38262 → 23 [SYN] Seq=0 Win=42340 Len=0 MSS=1460 SACK_PERM WS=4096 3145 82.558104256 192.168.0.242 → 8.8.8.8 TCP 66 [TCP Retransmission] 38262 → 23 [SYN] Seq=0 Win=42340 Len=0 MSS=1460 SACK_PERM WS=4096
- The connection from
192.168.0.242to8.8.8.8used destination port 23, the Telnet protocol.
ℹ️ Note: If
tsharkisn't available, capture withtcpdumpand analyze the trace offline in Wireshark. Runsudo tcpdump -i any -w fwcheck.pcapwhile reproducing the issue in a second console, then copy the capture file to a machine with Wireshark and filter ontcp.analysis.retransmissionto find the destination port the same way.
Finding a Blocked UDP Port
UDP has no handshake, so there's no retransmission to key off. Instead, filter directly for traffic to the destination.
- Resolve the destination hostname to its IP(s), since capture filters need an IP rather than a hostname:
nslookup time.google.com
Name: time.google.com Address: 216.239.35.0 Address: 216.239.35.4 Address: 216.239.35.8 Address: 216.239.35.12
- In Console 1, capture UDP traffic to those addresses. With multiple IPs, you can filter on each individually:
sudo tshark -Y "udp && (ip.dst == 216.239.35.0 or ip.dst == 216.239.35.4 or ip.dst == 216.239.35.8 or ip.dst == 216.239.35.12)" -T fields -e ip.src -e udp.srcport -e ip.dst -e udp.dstport
Or, when the IPs fall within the same CIDR block and can be summarized, filter on the network instead:
sudo tshark -Y "udp && ip.dst == 216.239.35.0/28" -T fields -e ip.src -e udp.srcport -e ip.dst -e udp.dstport
- In Console 2, run the command you're troubleshooting:
sudo ntpdate time.google.com
- Console 2 shows an error (on current Ubuntu releases
ntpdateis a wrapper aroundntpdig, which is what reports the failure):
ntpdig: no eligible servers
- Console 1 shows the traffic and destination port:
192.168.0.220 46648 216.239.35.12 123 192.168.0.220 33762 216.239.35.8 123 192.168.0.220 52219 216.239.35.4 123 192.168.0.220 47589 216.239.35.0 123
- Port 123 is in use, the NTP protocol.
If tshark isn't available, tcpdump works live without needing packet analysis. With multiple IPs, filter on each host individually:
sudo tcpdump -i any -nn udp and \( dst host 216.239.35.0 or dst host 216.239.35.12 or dst host 216.239.35.4 or dst host 216.239.35.8 \)
Or, when the IPs can be summarized into a CIDR block, filter on the network instead:
sudo tcpdump -i any -nn udp and dst net 216.239.35.0/28
ℹ️ Note: For offline analysis, capture with
tcpdump -was in the TCP section, then open the trace in Wireshark. For multiple IPs, filter on each individually:udp && (ip.addr == 216.239.35.0 or ip.addr == 216.239.35.4 or ip.addr == 216.239.35.8 or ip.addr == 216.239.35.12)Or, when the IPs can be summarized into a CIDR block, filter on the network instead:
udp && ip.addr == 216.239.35.0/28
Example
Suppose a VM in fwrules-demo runs a monitoring agent that needs to reach an external metrics endpoint, but the port it uses isn't documented anywhere. After removing the default egress rules, the agent can't send data and logs connection timeouts.
Following Step 4 above: start a tshark capture filtered on tcp.analysis.retransmission, restart the agent, and watch for the retransmitted SYN packets to the metrics endpoint's IP. The destination port in that output is the port to open — add an egress rule for it the same way as in Step 2, scoped to just that destination IP and port rather than 0.0.0.0/0.
Related Articles
- How-To Configure Firewall Rules for Crusoe Cloud Managed Load Balancers
- How-To Run MTR for Network Diagnostics
- How-To: Troubleshoot VM Network Issues Due to DNS Resolving to IPv6 Localhost