Skip to main content
Crusoe Support Help Center home page
Crusoe

How-To Restrict Internet Access from VMs and find ports that need to be open

David Cristobal Lopez
David Cristobal Lopez
Updated

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 sudo Access 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.

  1. Open two consoles: one to test, one to capture.
  2. In Console 1, capture retransmissions:
sudo tshark -Y "tcp.analysis.retransmission"
  1. 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
  1. Console 2 hangs on the connection attempt:
Trying 8.8.8.8...
  1. 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
  1. The connection from 192.168.0.242 to 8.8.8.8 used destination port 23, the Telnet protocol.

ℹ️ Note: If tshark isn't available, capture with tcpdump and analyze the trace offline in Wireshark. Run sudo tcpdump -i any -w fwcheck.pcap while reproducing the issue in a second console, then copy the capture file to a machine with Wireshark and filter on tcp.analysis.retransmission to 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.

  1. 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
  1. 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
  1. In Console 2, run the command you're troubleshooting:
sudo ntpdate time.google.com
  1. Console 2 shows an error (on current Ubuntu releases ntpdate is a wrapper around ntpdig, which is what reports the failure):
ntpdig: no eligible servers
  1. 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
  1. 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 -w as 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

Additional Resources

Related to

Was this article helpful?

0 out of 0 found this helpful

Still need help?

Our support team is ready to assist you with any questions.

Have more questions? Submit a request

Related Articles

Recently Viewed

Comments

0 comments

Article is closed for comments.