A simple, but powerful frontend for iptables.
resources
https://regrow.earth/diy-server/awall/
https://git.alpinelinux.org/awall/about/
https://wiki.alpinelinux.org/wiki/How-To_Alpine_Wall
https://wiki.alpinelinux.org/wiki/Zero-To-Awall
setup
Alpine doesn't come with ANY firewall by default so you'll need to start by
installing and enabling iptables:
doas apk add iptables ip6tables
doas modprobe ip_tables
doas modprobe ip6_tables
doas rc-service iptables save
doas rc-service ip6tables save
doas rc-service iptables start
doas rc-service ip6tables start
doas rc-update add iptables
doas rc-update add ip6tables
Then we'll install awall itself.
doas apk add awall
usage
Once you've written some policies you can list and enable them.
doas awall list
doas awall enable main outgoing ping incoming-ssh
doas awall disable ping
doas awall activate
policies
Awall's default config files are in /usr/share/awall, but any new policies we
add should go in /etc/awall/.
block all
The best way to setup any firewall is to begin with blocking everything and then selectively allow what is needed.
Dropping a packet simply ignores the packet completely whereas rejecting a packet tells the sender "this packet was rejected" and requires a bit more processing. Our default policy will simply drop packets coming from the outside, but reject the ones we are sending ourselves to give us a bit more information about what is going on in case we've made a mistake in our firewall config.
Create /etc/awall/optional/main.json:
{
"description": "Drop all incoming traffic from WAN, reject all other",
"zone": {
"WAN": { "iface": "eth0" }
},
"policy": [
{ "in": "WAN", "action": "drop" },
{ "action": "reject" }
]
}
block incoming, allow outgoing
Alternatively, you may prefer to trust all your local applications. This is less secure than manually allowing them, but it's not completely unreasonable:
{
"description": "Drop all incoming traffic from WAN, allow all outgoing",
"zone": {
"WAN": { "iface": "eth0" }
},
"policy": [
{ "in": "WAN", "action": "drop" },
{ "in": "_fw", "action": "allow" }
]
}
allow incoming ssh
Our goal for this policy is allowing SSH connections that are coming in over the internet. There is no need to allow outgoing SSH connections, so we will be as strict as possibly by only allowing incoming ones. We will also limit the amount of requests that can be made to 3 per 30 seconds to drop some connections from bots.
Create /etc/awall/optional/incoming-ssh.json:
{
"description": "Allow incoming SSH on WAN (TCP/22)",
"filter": [
{
"in": "WAN",
"out": "_fw",
"service": "ssh",
"action": "accept",
"conn-limit": { "count": 3, "interval": 30 }
}
]
}
First, we define which packets this policy is supposed to apply to. The packets
have to be coming from the outside "in": "WAN" and be addressed to a local
service on the server itself "out": "_fw".
The _fw zone basically just means "services on this computer". Then we specify
which protocol and port to use "service": "ssh". How does awall translate
ssh to mean 22? There is a default list of common services, which is located
at /usr/share/awall/mandatory/services.json. Writing ssh is just a shortcut
for { "proto": "tcp", "port": 22 }. So if your ssh daemon was listening on a
different port you might write "service": { "proto": "tcp", "port": 1234 },.
You can even define your own custom services in /etc/awall/private if you'd
like to be able to refer to them by name.
allow http
{
"description": "Allow incoming HTTP and HTTPS on WAN (TCP/22)",
"filter": [
{
"in": "WAN",
"out": "_fw",
"service": [ "http", "https" ],
"action": "accept"
}
]
}
allow basic outgoing services (DNS, HTTP, HTTPS, ping)
{
"description": "Allow basic outgoing traffic from local to WAN",
"filter": [
{
"in": "_fw",
"out": "WAN",
"service": [ "dns", "http", "https", "ping" ],
"action": "accept"
}
]
}
allow some incoming pings
{
"description": "Allow incoming ping on WAN with flow-limit",
"filter": [
{
"in": "WAN",
"out": "_fw",
"service": "ping",
"action": "accept",
"flow-limit": { "count": 10, "interval": 6 }
}
]
}
Unlike with our incoming SSH policy, we don’t use conn-limit to limit the
connections. Instead, we use flow-limit, which doesn't just limit the number
of new connections, but the number of packets. For SSH we don't want this,
because many packets could be exchanged after the initial connection attempt.
For ping, it is much simpler since each ping is one ICMP echo packet. So we
restrict the maximum number of incoming packets to 10 in 6 seconds.