The tags helped, thanks. The same lines in
/etc/iptables/iptables.rules are still truncated, though. I'll try to make sense of them by looking at the output from
iptables -L.
You didn't say anything about how much you know about
iptables, or if you're at all familiar with the way firewalls work in general, so I'll just comment and explain everything. (You had your chance...
)
I don't know anything about how your Linux distribution works, but it seems
/etc/iptables/iptables.rules is just a dump of the entire
iptables ruleset, generated by
iptables-save (just run
iptables-save from the command line and you'll see). Evidently, your distribution uses this file to store the rules, and loads them using
iptables-restore at bootup.
I will concentrate on the contents of this file as it appeared in your first post, as it contains the exact same rules as the list produced by
iptables -L, unless you've added or removed rules since you last booted the system. (Well, actually
iptables -L leaves out certain match criteria, so it's always best to dump the ruleset with
iptables-save.)
Quote:
Originally Posted by sandilovely24
*filter
|
This says that the rules following this statement are to be loaded into the "filter" table. There are three tables:
filter, which blocks or allows traffic;
nat, which manipulates the addresses and/or port numbers in packets ("Network Address Translation"), and
mangle, which alters or marks packets in different ways.
There are no "
*nat" or "
*mangle" statements anywhere, so it seems your system doesn't use the
nat or
mangle tables as all. This is not unusual for a standalone system.
Quote:
Originally Posted by sandilovely24
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]
:IN_SSH - [0:0]
:TCP - [0:0]
:UDP - [0:0]
:sshguard - [0:0]
|
Lines starting with a
: sets the policy for a chain in a table. The policy is how the system deals with traffic that doesn't match any specific rule. The line
sets the policy for the INPUT chain to "DROP", which means "drop any packets not explicitly allowed by a rule". It's the same as entering the command
iptables -t filter -P INPUT DROP at the command line.
The
filter table has three built-in chains: INPUT, FORWARD and OUTPUT. Any inbound traffic to the system itself is always processed by the rules in the INPUT chain, while traffic generated by the system is checked against the rules in the OUTPUT chain. The FORWARD chain is for inbound packets with a destination address that doesn't match any of the addresses assigned to the system, and thus need to be forwarded (routed). Only routers need rules in this chain.
In addition, your system has four user defined chains: "IN_SSH", "TCP", "UDP" and "sshguard". Such chains can contain rules just like the predefined chains, but will do nothing by themselves. They can be called from rules in any of the predefined chains. To understand the purpose of such chains, one has to look at how they are called and what rules they contain.
Quote:
Originally Posted by sandilovely24
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -m conntrack --ctstate INVALID -j DROP
|
These first and last of these rules in the INPUT chain deals with packets matching a certain "state". The Linux firewall keeps track of packets going in and out, and is able to determine whether a packet is a reply to a previous outbound packet, if it's a new request, or perhaps neither.
The first rule says "packets matching the Connection Tracker status RELATED or ESTABLISHED should be handled by the ACCEPT target". ESTABLISHED means a packet is a reply to a previous packet, while RELATED means the firewall considers it to be related to some other traffic, like an error message or a data stream opened by some allowed protocol. The "ACCEPT" target simply allows the packets in question.
The third rule sends packets matching the INVALID state (meaning the firewall can't make heads or tails of it) to the DROP target, which simply discards the packet.
The second rule simply allows internal traffic using the "lo" network interface. Traffic to this interface should never be blocked.
Quote:
Originally Posted by sandilovely24
-A INPUT -p icmp -m icmp --icmp-type 8 -m conntrack --ctstate NEW -j ACCEPT
|
This allows ICMP type 8 packets matching the NEW state. ICMP type 8 is "Echo" (better known as "ping"), and NEW means an incoming "ping" request from another host. In other words, others are allowed to "ping" your system. (Ping replies are not handled by this rule, but would be covered by the very first rule for ESTABLISHED packets.)
Quote:
Originally Posted by sandilovely24
-A INPUT -p udp -m conntrack --ctstate NEW -j UDP
-A INPUT -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -m conntrack --ctstate NE$
|
The latter of these rules has been truncated, as you can see. What is says, is "all TCP packets with the TCP flags FIN, SYN, RST, or ACK which are matching the state NEW [probably] should be sent [somewhere]". From the output from
iptables -L I can see that "somewhere" is in fact the user-defined chain "TCP". Apparently, any rules pertaining to TCP traffic can be found in this chain.
This makes sense in the context of the previous rule, which sends all UDP packets matching the NEW status to the user-defined chain called "UDP".
Quote:
Originally Posted by sandilovely24
-A INPUT -p udp -j REJECT --reject-with icmp-port-unreachable
-A INPUT -p tcp -j REJECT --reject-with tcp-reset
-A INPUT -j REJECT --reject-with icmp-proto-unreachable
|
The first of these rejects all UDP packets. To reach this rule, a UDP packet would have to match neither of the above rules, or be returned from the "UDP" chain, either manually through the RETURN target or because there were no matching rules in that chain.
The next rule does the same for TCP traffic, and the last handles any non-TCP/UDP traffic in much the same way.
This is probably a mistake, as it means the remaining rules in this chain are useless.
Quote:
Originally Posted by sandilovely24
-A INPUT -p icmp -m icmp --icmp-type 8 -m limit --limit 30/min --limit-burst 8 -$
-A INPUT -p icmp -m icmp --icmp-type 8 -j DROP
|
Another truncated rule here, one which handles ICMP packets. Not many such packets would get this far (only incoming pings, error messages and replies to outgoing pings, I believe), but this rules throttles how many such packets the system will allow through.
The first rule sends up to 30 packets/minute to the ACCEPT chain (again, the output from
iptables -L provided the clue), and then ICMP type 8 packets are dropped by the second rule. As type 8 packets were explicitly allowed by an earlier rule, no traffic will ever match the second rule.
Quote:
Originally Posted by sandilovely24
-A INPUT -p tcp -m tcp --dport 22 -j sshguard
|
Any incoming TCP packets to port 22 is sent to the "sshguard" user-defined chain. TCP port 22 is used by the SSH daemon, and presumably the "sshguard" chain is supposed to limit incoming SSH traffic in some way, but the chain is actually empty. As a result, any SSH packet will simply hit the end of that chain and return here to be processed by the rules below.
Quote:
Originally Posted by sandilovely24
-A INPUT -p tcp -m tcp --dport 22 -m conntrack --ctstate NEW -j IN_SSH
-A INPUT -p tcp -m tcp --dport 22 -m conntrack --ctstate NEW -j IN_SSH
-A INPUT -p icmp -m icmp --icmp-type 8 -m conntrack --ctstate NEW -j ACCEPT
-A INPUT -p tcp -m tcp --dport 22 -m conntrack --ctstate NEW -j IN_SSH
-A INPUT -p udp -m conntrack --ctstate NEW -j UDP
|
OK, more SSH rules. More than needed, actually; the first rule sends all SSH packets matching the NEW state to the "IN_SSH" user-defined chain. The next does exactky the same, which makes little sense.
Then follows three equally redundant rules; one allowing incoming "ping" packets (already allowed by an earlier rule), one sending SSH packets to the "IN_SSH" chain once again (could be problematic; see the IN_SSH chain below), and one sending UDP packets to the "UDP" chain (already done).
Quote:
Originally Posted by sandilovely24
-A IN_SSH -m recent --rcheck --seconds 10 --hitcount 3 --rttl --name sshbf --mas$
-A IN_SSH -m recent --rcheck --seconds 1800 --hitcount 4 --rttl --name sshbf --m$
-A IN_SSH -m recent --set --name sshbf --mask 255.255.255.255 --rsource -j ACCEPT
|
These three lines add three rules to the "IN_SSH" user-defined chain. The first two are truncated, but it's clear that in combination, these rules are meant to limit the amount of inbound SSH requests. The first rule keeps track of SSH packets and will only allow 3 such packets inside any 10 second window. The second allows up to 4 packets inside any 30 minute window. The last rule just creates/increments the counter.
Note that only SSH packets not matching the ESTABLISHED state will get far enough down the INPUT chain to reach the rule sending them to the "IN_SSH" chaion, so established SSH sessions will not be throttled or time out due to these rules. They probably exist to prevent brute force or dictionary password cracking attempts.
Unfortunately, there are THREE rules in the INPUT chain sending SSH packets to "IN_SSH". Each time, the packet is counted and control returned to the INPUT chain. As a result, even a single SSH packet is enough to fill the "max 3 packets per 10 second interval" quota, and a second attempt will also trigger the "max 4 packets per 30 minute interval" rule.
Quote:
Originally Posted by sandilovely24
-A TCP -p tcp -m tcp --dport 22 -j ACCEPT
-A TCP -p tcp -m tcp --dport 80 -j ACCEPT
-A TCP -p tcp -m tcp --dport 443 -j ACCEPT
-A TCP -p tcp -m tcp --dport 22 -j ACCEPT
|
The "TCP" chain accepts TCP traffic to ports 80, 443 and 22. Port 22 is SSH, but the first two ports are for web traffic. Are you running a web server on this system?
These rules are invoked when a packet reaches the corresponding rule in the INPUT chain, sending them to this chain for further processing.
Quote:
Originally Posted by sandilovely24
-A UDP -p udp -m udp --dport 53 -j ACCEPT
|
This rule allows inbound traffic to UDP port 53, which is the default port for DNS servers. If you're not running a publicly available DNS server on your system, the rule makes little sense and could possibly represent a security problem.
So, to sum it all up:
- Your INPUT chain allows "ping" and replies to outbound traffic (the ESTABLISHED and RELATED states)
- The INPUT chain sends SSH packets through the "sshguard" chain, then to the IN_SSH chain (both user-defined)
- TCP and UDP traffic is sent from the INPUT chain to the "TCP" and "UDP" user-defined chains respectively
- The "sshguard" chain does nothing
- The "IN_SSH" chain limits incoming SSH login attempts (returns non-blocked traffic to the calling chain)
- The "TCP" chain allows incoming HTTP, HTTPS and SSH packets (returns non-allowed traffic to the calling chain)
- The "UDP" chain allows DNS requests (returns non-allowed traffic to the calling chain)
- Unmatched packets reaching the bottom of the INPUT chain is dropped by the DROP policy
- The OUTPUT chain has no rules and an ALLOW policy
- The FORWARD chain has no rules and a DROP policy
Possible issues with this setup are:
- There's a blanket REJECT rule in the middle of the INPUT chain, blocking potentially useful traffic that's clearly meant to be let through (like SSH)
- SSH connection attempts are counted three times, which will trigger the blocking rules much earlier than intended
- Inbound traffic to the local web server is allowed, as well as DNS traffic. Unless you're running a web server (could be) and a public DNS server (highly unlikely), these rules should be removed.
And then a few observations (which are not errors):
<pedantic value="nitpick">
The "IN_SSH" chain does not really behave as one would expect. There's a rule in the INPUT chain sending SSH traffic to this chain, and I for one would expect the chain to handle anything and everything related to SSH. Instead, it blocks some SSH traffic and returns the rest, so there has to be an additional rule in the INPUT chain allowing SSH. I'd probably just stick the ACCEPT rule at the bottom of the SSH chain instead.
Same for the "TCP" and "UDP" chains, but with regards to blocked traffic. Once a packet is sent to the "TCP" or "UDP" chain for processing, I'd expect that to be the last I saw of it. Instead, the chains simply allow some traffic and return the rest. Why not
block the rest instead, as that's clearly the intention anyway?
</pedantic>