Configure firewall¶
When not using Docker¶
The firewall.sh script closes most ports by default. Its behavior is controlled by variables in the firewall-settings.local file.
Most variables are set by state files:
- SSH_IPV4 and SSH_IPV6
IPs from which to allow SSH collections. Set by the
firewall
state using Pillar data. See Connect to a server (SSH).- PUBLIC_HTTP
Opens port 80. Set by the
apache
state.- PUBLIC_HTTPS
Opens port 443. Set by the
apache
state.- PUBLIC_POSTGRESQL
Opens port 5432. Set by the
postgres
state, ifpostgres.public_access
isTrue
in Pillar.- PRIVATE_POSTGRESQL
Opens port 5432 to the replica servers. Set by the
postgres
state, ifpostgres.public_access
isn’tTrue
in Pillar.- REPLICA_IPV4 and REPLICA_IPV6
The IPs of replica servers. Set by the
postgres
state using Pillar data, ifpostgres.public_access
isn’tTrue
in Pillar.- PUBLIC_ELASTICSEARCH
Opens port 9200. Set by the
elasticsearch
state.- PUBLIC_TINYPROXY
Opens port 8888. Set by the
tinyproxy
state.- PRIVATE_PROMETHEUS_CLIENT
Opens port 7231 to the Prometheus server. Set by the
prometheus.node_exporter
state.- PROMETHEUS_IPV4 and PROMETHEUS_IPV6
The IPs of the Prometheus server. Set by the
prometheus.node_exporter
state using Pillar data.
Other variables are:
- PUBLIC_SSH
Opens port 22. Supersedes port knocking.
Open a port¶
If no variable corresponds to the port you need to open, update the firewall.sh
script and firewall-settings.local
template.
You might need to set variables if you’re working in a development environment. To set a variable, use the set_firewall
macro, for example:
{{ set_firewall('PUBLIC_SSH') }}
This sets PUBLIC_SSH="yes"
in the firewall-settings.local
file.
Close a port¶
Use the unset_firewall macro if a set_firewall
call is removed from a service’s state, whether directly (by deleting a set_firewall
call) or indirectly (by un-including a state file with set_firewall
calls).
Troubleshoot¶
When making changes to firewall settings or port assignments, you might want to:
Check if a port is open:
telnet host port
List active connections:
ss -tupln # netstat -tupln
When using Docker¶
The firewall.sh
script rewrites all iptables rules. However, Docker needs to add rules to route traffic to and from containers. To address this incompatibility, the firewall.sh
script exits if the docker
command exists. To implement firewall rules on Docker servers, we implement an external firewall.
Configure the external firewall:
Linode provide a stateful Cloud Firewall. Stateful firewalls can store information about connections over time, which is required for HTTP sessions and port knocking, for example.
Click the Firewalls menu item
Click the Create Firewall button
Enter the server name in Label
Select the server from the Linodes dropdown
Click the Create Firewall button
Click the new firewall’s label
Select “Drop” from the Default inbound policy dropdown
Add an inbound rule. The recommended minimum is:
Label
Protocol
Ports
Sources
Action
Allow-SSH
TCP
SSH (22)
All IPv4, All IPv6
Accept
Allow-ICMP
ICMP
All IPv4, All IPv6
Accept
Allow-Prometheus
TCP
7231
139.162.253.17/32, 2a01:7e00::f03c:93ff:fe13:a12c/128
Accept
Most servers will also have:
Label
Protocol
Ports
Sources
Action
Allow-HTTP
TCP
HTTP (80), HTTPS (443)
All IPv4, All IPv6
Accept
Click the Save Changes button
Click the Default project
Select the server
Click the Firewalls tab, and either:
Click the Apply Firewall button to reuse existing firewalls
Click the default firewall
Click the web firewall, if appropriate
Click the Apply # Firewall(s) button
Click the Create Firewall button to create a new firewall
Click the Add rule button under the Inbound rules heading. The default firewall is:
IPs
Protocol
Port
Any IPv4, Any IPv6
TCP
22
Any IPv4, Any IPv6
ICMP
139.162.253.17/32, 2a01:7e00::f03c:93ff:fe13:a12c/128
TCP
7231
The web firewall is:
IPs
Protocol
Port
Any IPv4, Any IPv6
TCP
80
Any IPv4, Any IPv6
TCP
443
Enter a name in Firewall name (“postgres”, for example)
Click the Create Firewall button
Hetzner Dedicated provide a free stateless firewall for each dedicated server. “Stateless” means that the firewall does not store information about connections over time, which is required for HTTP sessions and port knocking, for example.
Select the server
Click the Firewall tab
Select “active” from the Status dropdown
Check the Filter IPv6 packets box
Check the Hetzner Services (incoming) box
Select “SSH” from the Firewall template: dropdown and click Apply to fill in:
Name
Protocol
Source port
Destination port
TCP flags
Action
icmp
icmp
0-65535
accept
ssh
tcp
22
accept
tcp established
tcp
32768-65535
ack
accept
dns
udp
53
accept
Or, select “Webserver” from the Firewall template: dropdown and click Apply to also fill in:
Name
Protocol
Destination port
TCP flags
Action
http
tcp
80,443
accept
Add additional firewall rules. The recommended minimum is to also add:
Name
Protocol
Source IP
Destination port
TCP flags
Action
prometheus
tcp
139.162.253.17/32
7231
accept
Duplicate each firewall rule, suffixing -v6 to Name and setting Version to ipv6.
Note
Rules are duplicated, because Protocol can’t be set if Version is
*
. Skip the icmp and prometheus rules for ipv6 due to Hetzner limitations.Click Save and wait for the configuration to be applied.
Note
Destination IP and Source port are never set.
Reset the server-side firewall:
/home/sysadmin-tools/bin/firewall_reset.sh
Restart the Docker service, if running:
systemctl restart docker
Troubleshoot¶
If you configure an external firewall without resetting the server-side firewall, the server becomes inaccessible. Either:
- Recovery
Run
/home/sysadmin-tools/bin/firewall_reset.sh
as theroot
user
- Firewall
Open port 8255 in the external firewall
Connect to the server as the
root
userRun
/home/sysadmin-tools/bin/firewall_reset.sh
Close port 8255 in the external firewall
Note
On Azure, instead of the root
user, use the ocpadmin
user, and run commands with sudo
.