firewall setup

this is my iptables rules. i am a linux newbie and try to learn. do you think this is enough?

*filter
#  Allows all loopback (lo0) traffic and drop all traffic to 127/8 that doesn't use lo0
-A INPUT -i lo -j ACCEPT
-A INPUT ! -i lo -d 127.0.0.0/8 -j REJECT
#  Accepts all established inbound connections
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
#  Allows all outbound traffic
#  You can modify this to only allow certain traffic
-A OUTPUT -j ACCEPT
# Allows HTTP and HTTPS connections from anywhere (the normal ports for websites)
-A INPUT -p tcp --dport 80 -j ACCEPT
-A INPUT -p tcp --dport 443 -j ACCEPT
#  Allows SSH connections
# THE -dport NUMBER IS THE SAME ONE YOU SET UP IN THE SSHD_CONFIG FILE
-A INPUT -p tcp -m state --state NEW --dport 54321 -j ACCEPT
# Allow ping
-A INPUT -p icmp -m icmp --icmp-type 8 -j ACCEPT
# log iptables denied calls
-A INPUT -m limit --limit 5/min -j LOG --log-prefix "iptables denied: " --log-level 7
# Reject all other inbound - default deny unless explicitly allowed policy
-A INPUT -j REJECT
-A FORWARD -j REJECT
COMMIT

also do i have to insall nginx before php and mysql? what is the order? thanks.

5 Replies

You're blocking most ICMP traffic with those rules; this can break things like Path MTU Discovery. Otherwise looks decent. You'll be allowing incoming TCP connections to ports 80, 443, and 54321, and will have no restrictions on outgoing connections.

As for the order of installation… it doesn't really matter. If something needs to be installed before something else, almost all package managers will take care of it for you. Out of habit, I tend to do web server -> database server -> application, but that's totally arbitrary.

The real answer, of course, is to do whatever the Linode Library says to do ;-)

Thank you for your answer hoopycat. One last thing if i look at my iptable rules i see that it adds some extra codes above my rules. what is this, is this normal?

nano /etc/iptables.up.rules

these are the codes above my rules;

*security
:INPUT ACCEPT [3066:255554]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [2617:280883]
COMMIT
# Completed on Fri Nov 11 12:51:12 2011
# Generated by iptables-save v1.4.4 on Fri Nov 11 12:51:12 2011
*raw
:PREROUTING ACCEPT [3076:259024]
:OUTPUT ACCEPT [2617:280883]
COMMIT
# Completed on Fri Nov 11 12:51:12 2011
# Generated by iptables-save v1.4.4 on Fri Nov 11 12:51:12 2011
*nat
:PREROUTING ACCEPT [61:5834]
:INPUT ACCEPT [51:2364]
:OUTPUT ACCEPT [208:15776]
:POSTROUTING ACCEPT [208:15776]
COMMIT
# Completed on Fri Nov 11 12:51:12 2011
# Generated by iptables-save v1.4.4 on Fri Nov 11 12:51:12 2011
*mangle
:PREROUTING ACCEPT [3076:259024]
:INPUT ACCEPT [3066:255554]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [2617:280883]
:POSTROUTING ACCEPT [2617:280883]
COMMIT
# Completed on Fri Nov 11 12:51:12 2011
# Generated by iptables-save v1.4.4 on Fri Nov 11 12:51:12 2011

That's the output from "iptables-save", which is formatted to let "iptables-restore" load everything in the right order. Most of the entries you pasted are the defaults for other tables.

hoopycat you said "You're blocking most ICMP traffic with those rules; this can break things like Path MTU Discovery. Otherwise looks decent." can you share a decent firewall setup without break things like Path MTU Discovery. For example can you share your own setup? Thanks.

@bboran:

hoopycat you said "You're blocking most ICMP traffic with those rules; this can break things like Path MTU Discovery. Otherwise looks decent." can you share a decent firewall setup without break things like Path MTU Discovery. For example can you share your own setup? Thanks.

Certainly. I've got a few different ones, depending on the situation. None of them are probably what you're after, but it's all about ideas and thoughts. Worth noting is that every single one of these uses iptables "under the hood", although the front end is different.

tremens: netbook. Connects to hostile networks on a myriad of interfaces (two ethernets, three wifis, and 3G). Attempts to bring up an OpenVPN connection to a Linode whenever it can. I use ufw to handle the firewalling.

Allowed from anywhere: ssh, printing (?!!), multicast DNS (also ??!!), munin (which should probably only be allowed over OpenVPN).

Allowed from my home IPv4 /24 on Ethernet only: Dropbox (not a 100% effective rule, but I think this was a bandwidth management thing).

Summary: easy to add rules, also easy to add something then forget wtf you added it. Everything works fine, though.

rtucker@tremens:~$ sudo ufw status
[sudo] password for rtucker: 
Status: active

To                         Action      From
--                         ------      ----
OpenSSH                    ALLOW       Anywhere
CUPS                       ALLOW       Anywhere
5353/udp                   ALLOW       Anywhere
4949/tcp                   ALLOW       Anywhere
17500 on eth0              ALLOW       192.168.1.0/24
OpenSSH (v6)               ALLOW       Anywhere (v6)
CUPS (v6)                  ALLOW       Anywhere (v6)
5353/udp                   ALLOW       Anywhere (v6)
4949/tcp                   ALLOW       Anywhere (v6)

budweiser: router. Provides IPv4 NAT and IPv6 routing, with firewalling for both. For the IPv4 input side of things, ICMP and DHCP replies are explicitly allowed from the Internet side of things, but everything else (except for established connections) gets dropped. This is kind of implicit with NAT, of course, but it's nice to make things explicit. On the forward chain, I icmp-host-unreachable everything to hit-nxdomain.opendns.com, except TCP port 80. This is the IP that OpenDNS returns along with NXDOMAIN errors. This lets me at least error out quickly when I typo something that isn't HTTP!

[rtucker@budweiser.rochnyav] /ip firewall filter> export
# nov/13/2011 19:36:20 by RouterOS 5.7
# software id = PZKV-3VJG
#
/ip firewall filter
add action=accept chain=input comment="Allow ICMP from Internet" disabled=no \
    protocol=icmp
add action=accept chain=input comment="Allow DHCP replies" disabled=no \
    dst-port=68 protocol=udp src-port=67
add action=accept chain=input comment="Allow established connections" \
    connection-state=established disabled=no in-interface=ether1-gateway-twc
add action=accept chain=input connection-state=related disabled=no \
    in-interface=ether1-gateway-twc
add action=log chain=input comment="Drop everything else" disabled=no \
    in-interface=ether1-gateway-twc limit=1,5 log-prefix="IPv4 Input Drop"
add action=reject chain=input disabled=no in-interface=ether1-gateway-twc \
    reject-with=icmp-admin-prohibited
add action=accept chain=forward comment=\
    "allow port 80 to opendns nxdomain handler, reject others" disabled=no \
    dst-address=67.215.65.132 dst-port=80 protocol=tcp
add action=reject chain=forward disabled=no dst-address=67.215.65.132 \
    reject-with=icmp-host-unreachable

The IPv6 end of things is a little more interesting, since there is no NAT involved. The input chain is just for traffic to the router itself (established connections allowed, new outbound connections allowed, ICMPv6 allowed, all else rejected), but the forward chain protects all the hosts. Again, established connections, new outbound connections, and ICMPv6 connections are allowed. In addition:

  • Protocol 59, packets of size 40. I think this was something BitTorrent-related, but like a moron, I didn't use the "comment" field.

  • Ports 22, 53, 80, 514 (syslog-ng for off-site stuff logging to here), 631 (printing, from off-site servers), 4949 (munin, from off-site servers), 51413 (bittorrent) are allowed

  • Everything else -> drop

[rtucker@budweiser.rochnyav] /ipv6 firewall filter> export
# nov/13/2011 19:40:45 by RouterOS 5.7
# software id = PZKV-3VJG
#
/ipv6 firewall filter
add action=accept chain=input comment="Accept in-progress connections" \
    connection-state=related disabled=no
add action=accept chain=input connection-state=established disabled=no
add action=accept chain=input comment="Allow new connections from the inside" \
    connection-state=new disabled=no in-interface=bridge-mainlan
add action=accept chain=input comment="Allow ICMPv6" disabled=no protocol=\
    icmpv6
add action=log chain=input comment=\
    "final rule: reject incoming traffic from the internet" disabled=no \
    in-interface=tunnel-he-nyc limit=1,5 log-prefix="IPv6 Input Reject"
add action=reject chain=input disabled=no in-interface=tunnel-he-nyc
add action=accept chain=forward comment="Allow in-progress connections" \
    connection-state=established disabled=no
add action=accept chain=forward connection-state=related disabled=no
add action=accept chain=forward comment="Allow new connections from inside" \
    connection-state=new disabled=no in-interface=bridge-mainlan
add action=accept chain=forward comment="Allow ICMPv6" disabled=no protocol=\
    icmpv6
add action=accept chain=forward disabled=no in-interface=tunnel-he-nyc \
    packet-size=40 protocol=59
add action=accept chain=forward comment=\
    "Allow selected connections from the outside" disabled=no dst-port=22 \
    in-interface=tunnel-he-nyc protocol=tcp
add action=accept chain=forward disabled=no dst-port=53 in-interface=\
    tunnel-he-nyc protocol=tcp
add action=accept chain=forward disabled=no dst-port=80 in-interface=\
    tunnel-he-nyc protocol=tcp
add action=accept chain=forward disabled=no dst-port=514 in-interface=\
    tunnel-he-nyc protocol=tcp
add action=accept chain=forward disabled=no dst-port=631 in-interface=\
    tunnel-he-nyc protocol=tcp src-address-list=cdknnjln
add action=accept chain=forward disabled=no dst-port=4949 in-interface=\
    tunnel-he-nyc protocol=tcp src-address-list=cdknnjln
add action=accept chain=forward disabled=no dst-port=51413 in-interface=\
    tunnel-he-nyc protocol=tcp
add action=accept chain=forward disabled=no dst-port=53 in-interface=\
    tunnel-he-nyc protocol=udp
add action=accept chain=forward disabled=no dst-port=123 in-interface=\
    tunnel-he-nyc protocol=udp
add action=accept chain=forward disabled=no dst-port=514 in-interface=\
    tunnel-he-nyc protocol=udp
add action=accept chain=forward disabled=no dst-port=51413 in-interface=\
    tunnel-he-nyc protocol=udp
add action=log chain=forward comment=\
    "Drop all other traffic from the Internet" disabled=no in-interface=\
    tunnel-he-nyc log-prefix="IPv6 Ingress Forward Reject"
add action=reject chain=forward disabled=no in-interface=tunnel-he-nyc

Summary: It doesn't look anything at all like iptables, but it's iptables under the hood. You'll find Linux in a lot of places, and where you find Linux, you find iptables. Also, remember to add comments when you do things so you remember why the heck you did them. Like printing on tremens, or… packet-size=40 protocol=59 on my home router (?!).

framboise: a Linode handling HTTP, HTTPS, NTP, VPN and SIP traffic. You were waitin' for this one, I bet.

There's a lot going on here. I'll take the tables in order:

# Generated by iptables-save v1.4.10 on Thu Jun 30 21:16:48 2011
*raw
:PREROUTING ACCEPT [68455649:8697451231]
:OUTPUT ACCEPT [60311411:6536857497]
-A PREROUTING -d 97.107.134.213/32 -p udp -m udp --dport 123 -j NOTRACK 
-A PREROUTING -d 97.107.131.4/32 -p udp -m udp --dport 123 -j NOTRACK 
-A OUTPUT -s 97.107.134.213/32 -p udp -m udp --sport 123 -j NOTRACK 
-A OUTPUT -s 97.107.131.4/32 -p udp -m udp --sport 123 -j NOTRACK 
COMMIT
# Completed on Thu Jun 30 21:16:48 2011

In the 'raw' table, I'm disabling connection tracking for NTP traffic (UDP port 123). I can't just outright disable connection tracking, but with hundreds of NTP queries per second, things get bad if I don't do something. mnordhoff gets the credit for this trick.

# Generated by iptables-save v1.4.10 on Thu Jun 30 21:16:48 2011
*nat
:PREROUTING ACCEPT [831087:77525111]
:INPUT ACCEPT [826420:77230543]
:OUTPUT ACCEPT [87206:5578202]
:POSTROUTING ACCEPT [86962:5484951]
-A PREROUTING -i tun1 -p udp -m udp --dport 53 -j DNAT --to-destination 208.67.222.222 
-A PREROUTING -i tun1 -p tcp -m tcp --dport 53 -j DNAT --to-destination 208.67.222.222 
-A POSTROUTING -s 172.23.100.0/30 -o eth0 -j MASQUERADE 
-A POSTROUTING -s 172.23.101.0/24 -o eth0 -j MASQUERADE 
COMMIT
# Completed on Thu Jun 30 21:16:48 2011

In the 'nat' table, I'm doing NAT for my VPN connections. (Duh!). Only fancy thing here is the DNAT for port 53: no matter what my netbook thinks its DNS is, stuff will be directed to OpenDNS. This is easier than battling network-manager every time I connect to a new network.

# Generated by iptables-save v1.4.10 on Thu Jun 30 21:16:48 2011
*filter
:INPUT ACCEPT [21639:3081430]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [21001:2716679]
-A INPUT -d 97.107.134.213/32 
-A INPUT -d 97.107.131.4/32 
-A INPUT -d 192.168.137.246/32 
-A INPUT -d 172.23.100.1/32 
-A INPUT -d 172.23.101.1/32 
-A INPUT -s <redacted>/32 
-A INPUT -s <redacted>/32 -j REJECT --reject-with icmp-port-unreachable 
-A INPUT -s <redacted>/32 -j REJECT --reject-with icmp-port-unreachable 
-A INPUT -s 10.0.0.0/8 -i eth0 -j REJECT --reject-with icmp-admin-prohibited 
-A INPUT -s 172.16.0.0/12 -i eth0 -j REJECT --reject-with icmp-admin-prohibited 
-A INPUT -s 192.168.0.0/17 -i eth0 -j REJECT --reject-with icmp-admin-prohibited 
-A INPUT -s 169.254.0.0/16 -i eth0 -j REJECT --reject-with icmp-admin-prohibited 
-A INPUT -i eth0 -p udp -m udp --dport 5060 -m recent --rcheck --seconds 10 --hitcount 20 --name SIP --rsource -m limit --limit 1/sec --limit-burst 3 -j LOG --log-prefix "Dropped (SIP 20/10s): " 
-A INPUT -i eth0 -p udp -m udp --dport 5060 -m recent --update --seconds 10 --hitcount 20 --name SIP --rsource -j DROP 
-A INPUT -i eth0 -p udp -m udp --dport 5060 -m recent --rcheck --seconds 2 --hitcount 10 --name SIP --rsource -m limit --limit 1/sec --limit-burst 3 -j LOG --log-prefix "Dropped (SIP 10/2s): " 
-A INPUT -i eth0 -p udp -m udp --dport 5060 -m recent --update --seconds 2 --hitcount 10 --name SIP --rsource -j DROP 
-A INPUT -i eth0 -p udp -m udp --dport 5060 -m recent --set --name SIP --rsource 
-A FORWARD -d 10.0.0.0/8 -o eth0 -j REJECT --reject-with icmp-admin-prohibited 
-A FORWARD -d 172.16.0.0/12 -o eth0 -j REJECT --reject-with icmp-admin-prohibited 
-A FORWARD -d 192.168.0.0/17 -o eth0 -j REJECT --reject-with icmp-admin-prohibited 
-A FORWARD -d 169.254.0.0/16 -o eth0 -j REJECT --reject-with icmp-admin-prohibited 
-A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT 
-A FORWARD -s 172.23.100.0/30 -i tun1 -j ACCEPT 
-A FORWARD -s 172.23.101.0/24 ! -i eth0 -j ACCEPT 
-A FORWARD -j REJECT --reject-with icmp-port-unreachable 
-A OUTPUT -s 97.107.134.213/32 
-A OUTPUT -s 97.107.131.4/32 
-A OUTPUT -s 192.168.137.246/32 
-A OUTPUT -s 172.23.100.1/32 
-A OUTPUT -s 172.23.101.1/32 
-A OUTPUT -d <redacted>/32 
-A OUTPUT -d 10.0.0.0/8 -o eth0 -j REJECT --reject-with icmp-admin-prohibited 
-A OUTPUT -d 172.16.0.0/12 -o eth0 -j REJECT --reject-with icmp-admin-prohibited 
-A OUTPUT -d 192.168.0.0/17 -o eth0 -j REJECT --reject-with icmp-admin-prohibited 
-A OUTPUT -d 169.254.0.0/16 -o eth0 -j REJECT --reject-with icmp-admin-prohibited 
COMMIT
# Completed on Thu Jun 30 21:16:48 2011</redacted></redacted></redacted></redacted> 

A whole lot of stuff going on in the filter table, as you can guess. Those INPUT and OUTPUT rules with no actions on them are for counters, used by munin's ip_ plugin. There's reject rules for specific IP addresses that have caused problems, too. The rules for SIP (port 5060) are kinda cool… basically, rate-limiting VoIP signalling traffic. (It turns out there's no small number of idiots who set their VoIP phones to try to register to pool.ntp.org, and no small number of VoIP phones that didn't bother implementing the sleep() syscall. This has caused Problems.) On the FORWARD chain, we have the companions to the NAT rules.

On the IPv6 side of things, all I have are a bunch of auto-generated rules with no action, like those on the IPv4 side. I'll omit them for brevity.

Summary: You can have a lot of fun with iptables without denying much traffic. I do enough experimental stuff that keeping things open is the most flexible policy. This does mean that anything can bind to a port and accept connections from the Internet unimpeded, but that's kind of useful for experimentation. I could (and should) probably implement a policy similar to the IPv6 rules on budweiser, though, and only allow "known good" traffic. (This is a little tricky with SIP, though.)

From the start, Linux has been fairly sane about network security. If there's nothing listening on a port, there's (assuming bug-free software) nothing a packet to that port can do to harm a system. But there's always a risk that a human will bung up the configuration and make something open to the Internet that shouldn't be, or that some bug will appear somewhere. So, explicitly allowing things and denying everything else is probably a good policy.

Reply

Please enter an answer
Tips:

You can mention users to notify them: @username

You can use Markdown to format your question. For more examples see the Markdown Cheatsheet.

> I’m a blockquote.

I’m a blockquote.

[I'm a link] (https://www.google.com)

I'm a link

**I am bold** I am bold

*I am italicized* I am italicized

Community Code of Conduct