LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Server (https://www.linuxquestions.org/questions/linux-server-73/)
-   -   Are these iptables rules enough for a web server? (https://www.linuxquestions.org/questions/linux-server-73/are-these-iptables-rules-enough-for-a-web-server-4175733044/)

Jason.nix 01-22-2024 01:09 AM

Are these iptables rules enough for a web server?
 
Hello,
I have a server running Apache, Tor (Port 9050) and OpenVPN (Port 2024). Are the following iptables rules good and sufficient?
Code:

-P INPUT DROP
-P OUTPUT ACCEPT
-P FORWARD DROP

-A INPUT -i lo -j ACCEPT
-A OUTPUT -o lo -j ACCEPT

-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT

-A INPUT -p icmp --icmp-type 0 -m state --state ESTABLISHED,RELATED -j ACCEPT

-A INPUT -p tcp -m state --state NEW -m recent --update --seconds 60 --hitcount 20 -j DROP
-A INPUT -p tcp -m state --state NEW -m recent --set -j ACCEPT

-A INPUT -p udp -m udp --dport 2024 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 9050 -j ACCEPT

-A INPUT -s IP -p tcp -m tcp --dport 22 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
-A INPUT -p tcp -m tcp --dport 22 -j DROP

-A INPUT -s IP -i eth0 -p tcp --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT
-A INPUT -s IP -i eth0 -p tcp --dport 443 -m state --state NEW,ESTABLISHED -j ACCEPT

-A INPUT -p tcp --dport 443 -m limit --limit 25/minute --limit-burst 100 -j ACCEPT

Regarding the web server I found the following rules and I have two questions:
Code:

# Allow incoming HTTP
-A INPUT -s IP -i eth0 -p tcp --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT
-A OUTPUT -o eth0 -p tcp --sport 80 -m state --state ESTABLISHED -j ACCEPT

# Allow incoming HTTPS
-A INPUT -s IP -i eth0 -p tcp --dport 443 -m state --state NEW,ESTABLISHED -j ACCEPT
-A OUTPUT -o eth0 -p tcp --sport 443 -m state --state ESTABLISHED -j ACCEPT

1- Why OUTPUT?
2- When you want to use HTTPS, is port 80 necessary?

Thank you.

Turbocapitalist 01-22-2024 01:46 AM

It looks like you leave the loopback interface open for spoofing. It should only accept input and output to and from its own address range.

Why are you rate limiting HTTPS and not HTTP?

You also risk locking yourself out with SSH if you fat finger the IP address range or need to log in from another. That should be open but the authentication limited to only either keys or certificates with password authentication off.

Port 80 (HTTP) is necessary with HTTPS if you are setting up Let's Encrypt certificates for your TLS. The CertBot, or other method, will need to occasionally publish something for verification.

Since you default a generic output policy of Allow, then the extra lines explicitly allowing HTTP and HTTPS are not needed. If you turn the output policy to Drop, then you will need to also open up outgoing DNS and presumably SMTP or other operational services.

A loose set of rules which could be converted:

Code:

#!/usr/sbin/nft -f

# Clear all prior state
flush ruleset

# Basic IPv4/IPv6 stateful firewall
table inet filter {

        chain input {
                type filter hook input priority 0; policy drop;

                # accept local host traffic
                iifname "lo" ip saddr 127.0.0.0/8 ip daddr 127.0.0.0/8 \
                counter accept
                iifname "lo" ip6 saddr ::1 ip6 daddr ::1 \
                counter accept

                #  Accept traffic originated from us
                ct state { established, related } accept

                # Drop invalid connections
                ct state invalid drop

                # Reject AUTH to make it fail fast
                tcp dport 113 reject with icmpx type port-unreachable

                tcp dport  22 ct state new limit rate 4/minute counter accept
                tcp dport  80 ct state new accept
                tcp dport  443 ct state new accept

                # ICMPv4
                # Accept ICMP
                ip protocol icmp icmp type {
                        echo-reply,  # type 0
                        destination-unreachable,  # type 3
                        echo-request,  # type 8
                        time-exceeded,  # type 11
                        parameter-problem,  # type 12
                } accept

                # ICMPv6
                # Accept basic IPv6 functionality
                ip6 nexthdr icmpv6 icmpv6 type {
                        destination-unreachable,  # type 1
                        packet-too-big,  # type 2
                        time-exceeded,  # type 3
                        parameter-problem,  # type 4
                        echo-request,  # type 128
                        echo-reply,  # type 129
                } accept

                #  Allow IPv6 SLAAC
                ip6 nexthdr icmpv6 icmpv6 type {
                        nd-router-solicit,  # type 133
                        nd-router-advert,  # type 134
                        nd-neighbor-solicit,  # type 135
                        nd-neighbor-advert,  # type 136
                } ip6 hoplimit 255 accept

                # Allow IPv6 multicast listener discovery on link-local
                ip6 nexthdr icmpv6 icmpv6 type {
                        mld-listener-query,  # type 130
                        mld-listener-report,  # type 131
                        mld-listener-reduction,  # type 132
                        mld2-listener-report,  # type 143
                } ip6 saddr fe80::/10 accept

                #  Accept DHCPv6 replies from IPv6 link-local addresses
                ip6 saddr fe80::/10 udp sport 547 udp dport 546 accept
        }

        chain forward {
                type filter hook forward priority 0; policy drop;
        }

        chain output {
                type filter hook output priority 0; policy accept;

}

include "/etc/nftables.d/*.nft"

Jason.nix 01-22-2024 05:25 AM

Quote:

Originally Posted by Turbocapitalist (Post 6478493)
It looks like you leave the loopback interface open for spoofing. It should only accept input and output to and from its own address range.

Why are you rate limiting HTTPS and not HTTP?

You also risk locking yourself out with SSH if you fat finger the IP address range or need to log in from another. That should be open but the authentication limited to only either keys or certificates with password authentication off.

Port 80 (HTTP) is necessary with HTTPS if you are setting up Let's Encrypt certificates for your TLS. The CertBot, or other method, will need to occasionally publish something for verification.

Since you default a generic output policy of Allow, then the extra lines explicitly allowing HTTP and HTTPS are not needed. If you turn the output policy to Drop, then you will need to also open up outgoing DNS and presumably SMTP or other operational services.

A loose set of rules which could be converted:

Code:

#!/usr/sbin/nft -f

# Clear all prior state
flush ruleset

# Basic IPv4/IPv6 stateful firewall
table inet filter {

        chain input {
                type filter hook input priority 0; policy drop;

                # accept local host traffic
                iifname "lo" ip saddr 127.0.0.0/8 ip daddr 127.0.0.0/8 \
                counter accept
                iifname "lo" ip6 saddr ::1 ip6 daddr ::1 \
                counter accept

                #  Accept traffic originated from us
                ct state { established, related } accept

                # Drop invalid connections
                ct state invalid drop

                # Reject AUTH to make it fail fast
                tcp dport 113 reject with icmpx type port-unreachable

                tcp dport  22 ct state new limit rate 4/minute counter accept
                tcp dport  80 ct state new accept
                tcp dport  443 ct state new accept

                # ICMPv4
                # Accept ICMP
                ip protocol icmp icmp type {
                        echo-reply,  # type 0
                        destination-unreachable,  # type 3
                        echo-request,  # type 8
                        time-exceeded,  # type 11
                        parameter-problem,  # type 12
                } accept

                # ICMPv6
                # Accept basic IPv6 functionality
                ip6 nexthdr icmpv6 icmpv6 type {
                        destination-unreachable,  # type 1
                        packet-too-big,  # type 2
                        time-exceeded,  # type 3
                        parameter-problem,  # type 4
                        echo-request,  # type 128
                        echo-reply,  # type 129
                } accept

                #  Allow IPv6 SLAAC
                ip6 nexthdr icmpv6 icmpv6 type {
                        nd-router-solicit,  # type 133
                        nd-router-advert,  # type 134
                        nd-neighbor-solicit,  # type 135
                        nd-neighbor-advert,  # type 136
                } ip6 hoplimit 255 accept

                # Allow IPv6 multicast listener discovery on link-local
                ip6 nexthdr icmpv6 icmpv6 type {
                        mld-listener-query,  # type 130
                        mld-listener-report,  # type 131
                        mld-listener-reduction,  # type 132
                        mld2-listener-report,  # type 143
                } ip6 saddr fe80::/10 accept

                #  Accept DHCPv6 replies from IPv6 link-local addresses
                ip6 saddr fe80::/10 udp sport 547 udp dport 546 accept
        }

        chain forward {
                type filter hook forward priority 0; policy drop;
        }

        chain output {
                type filter hook output priority 0; policy accept;

}

include "/etc/nftables.d/*.nft"

Hello,
Thank you so much for your reply.
Quote:

It looks like you leave the loopback interface open for spoofing. It should only accept input and output to and from its own address range.
How?

Quote:

Why are you rate limiting HTTPS and not HTTP?
Sorry, I forgot it!

Quote:

Since you default a generic output policy of Allow, then the extra lines explicitly allowing HTTP and HTTPS are not needed. If you turn the output policy to Drop, then you will need to also open up outgoing DNS and presumably SMTP or other operational services.
I use Tor and OpenVPN on this web server. Tor must access the outside of the server to communicate. Am I wrong?

Are the following lines necessary?
Code:

-A OUTPUT -o eth0 -p tcp --sport 80 -m state --state ESTABLISHED -j ACCEPT
-A OUTPUT -o eth0 -p tcp --sport 443 -m state --state ESTABLISHED -j ACCEPT



All times are GMT -5. The time now is 05:41 AM.