iptables --sport vs --dport. INPUT vs OUTPUT - linux

I am having some trouble understanding iptables. I know it acts as a filter but something isn't clicking because it isn't working the way I think it should. Let me start by saying that I'm creating a white list, so all policies (INPUT, FORWARD, OUTPUT) default to DROP.
I have the following rules related to SMTP:
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A INPUT -p tcp --dport 25 -j ACCEPT
-A OUTPUT -p tcp --dport 25 -j ACCEPT //needed for receiving?
-A OUTPUT -p tcp --sport 25 -j ACCEPT //needed for sending?
*these 3 lines also exist verbatim for ports 587 & 465
If I remove the first OUTPUT line then my server won't receive emails & if I remove the last line it won't send emails. What I don't understand is why. Shouldn't:
-A INPUT -p tcp --dport 25 -j ACCEPT
-A OUTPUT -p tcp --sport 25 -j ACCEPT
be enough to let everything through? AFAIK all SMTP communication should go over 25, 587 or 465. My current understanding says an SMTP packet should always match one of these two rules. All input packets should come to port 25, and all output packets be sent from 25? What am I missing?

For SMTP you don't need any --sport rule. The source and destination don't depend on direction - they're match on the packet's source and destination ports. Every connection will have a random source port, so there's nothing to match on.
If I remove the first OUTPUT line then my server won't receive emails & if I remove the last line it won't send emails.
This is wrong. Only the INPUT line matters for receiving emails. Also, only the OUTPUT --dport 25 line matters for sending emails. So these rules should be enough:
-A INPUT -p tcp --dport 25 -j ACCEPT
-A OUTPUT -p tcp --dport 25 -j ACCEPT
The problem may be that you set OUTPUT to default to DROP, but allowed established connection on INPUT only. Usually people leave OUTPUT defaulting to ACCEPT. If you want to continue using a whitelist for OUTPUT, you'll have to add:
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
Also, please read up on SMTP ports. Some of those you listed are only needed for email submissions and deprecated encryption, not for server-to-server communication. This may change how you plan your rules.

Previous answer state: Also, only the OUTPUT --dport 25 line matters for sending emails.
This is not always true. For instance some systems are configured as smarthost where the MTA become a client. In such case, the MTA will connect to a remote server on submission port (587) USING SASL authentication to send mails.
To resume, a client is sending mail through a remote server and the remote server itself connect to another remote server on port 587 with SASL authentication.
In such case, the following iptable rules applies (for the smarthost)
iptables -I OUTPUT -p -tcp -dport 597 -j ACCEPT
iptables -I INPUT -p -tcp -sport 587 -j ACCEPT

Related

IP Table rule to drop TCP packet and connection if PSH payload does not begin with specific bytes

We have an old multiplayer game (no source code) which crashes any time someone sends the server unexpected packets, and many of the players use telnet to do it with ease. I'm using iptables, and I want to filter out packets (and drop the connection) that the game server will not recognize. I want to do the following to the game server's port:
Pseudocode
if (PSH flag && Payload.Length > 0 bytes && Payload.Length < 6 bytes)
{
// reject data, and drop client
}
else if (PSH flag && Payload.Length > 2)
{
if (First3BytesOfPayload Not in [7f:ef:09, dc:0b:09, 08:00:09])
{
// reject data, and drop client
}
}
This is not a foolproof solution, but it should work good enough for the few people we have. How can I accomplish this with iptables, if at all?
Thank you for your time.
I figured it out. I did it with the rules below (not all the rules), and it works wonderfully. I suppose I could have used the iptables length option, but I didn't need it. Anyone deciding to do this should make it specific to a port, and understand their program's tcp messaging protocol first, or else you may get locked out.
iptables -A INPUT -p tcp --dport 1949 --tcp-flags ALL PSH,ACK -m u32 --u32 "39&0xFFFFFF=0x7fef09" -j ACCEPT
iptables -A INPUT -p tcp --dport 1949 --tcp-flags ALL PSH,ACK -m u32 --u32 "39&0xFFFFFF=0xdc0b09" -j ACCEPT
iptables -A INPUT -p tcp --dport 1949 --tcp-flags ALL PSH,ACK -m u32 --u32 "39&0xFFFFFF=0x080009" -j ACCEPT
iptables -A INPUT -p tcp --dport 1949 --tcp-flags ALL PSH,ACK -j DROP

linux firewall rule - iptables –A INPUT rule that will accept any packet that comes in over ports 43,53 or 67

I need an linux firewall rule that will accomplish the following: iptables –A INPUT rule that will accept any packet that comes in over ports 43,53 or 67.
I am new to this. Do you have to have -p "protocol" before --dport 43,53,67 or can you take out the -p "protocol" and just have the --dport 43,53,67. How would you have accept any packet that could come over multiple protocols?
You have to use it for all protocols you want to allow
iptables -A INPUT -p tcp -m multiport --dports 43,53,67 -j ACCEPT
iptables -A INPUT -p udp -m multiport --dports 43,53,67 -j ACCEPT
--dport is not a flag for general iptables rules. It's a flag for one of it's extended packet matching modules. These are loaded when you use -p protocol or -m. Unless you specify -m <protocol> or -p <protocol> with a specific protocol you can't use --dport

How to block udp ports range in linux RHEL7

need to test an application which uses the UDP port range from 5000 to 60,000 in. i want to test the boundary value condition for ports. so i want to block UDP ports range from 5000 to 59999.
Using iptables:
iptables -A INPUT -p udp --dport 5000:59999 -j DROP
or, better,
iptables -A INPUT -p udp --dport 5000:59999 -j REJECT --reject-with icmp-port-unreachable

Can't Access Port number 80 and 443 after adding Iptables rules

In my CentOS 6 i added a IPtables rules like DROP all the policy like
iptables -P INPUT DROP
Then I allow Port NO 22,80,443 with this command,
iptables -A INPUT -i eth0 -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -i eth0 -p tcp --dport 443 -j ACCEPT
iptables -A INPUT -i eth0 -p tcp --dport 22 -j ACCEPT
Now can access SSH with putty. But i can't access Internet. I have to know the exact problem of this.? Please help me.
Ofcourse you cannot access the Internet. You just added a rule that drops all incoming traffic (except for traffic coming in to ports 22, 80 and 443).
When you try to access the internet (if you're using a browser), your machine establishes a connection from
<local IP>:<port1> <----> <remote IP>:80
When the remote server responds to you, it will respond back to the same port1 that you sent the request from (which will NOT be 22, or 80, or 443. It will be a number usually higher than 32768), so it will get dropped by iptables.
Try these rules instead:
iptables -P INPUT DROP
iptables -I INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -i eth0 -p tcp --dport 22 -j ACCEPT
iptables -A INPUT -i eth0 -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -i eth0 -p tcp --dport 443 -j ACCEPT
The second rule tells IP tables to ACCEPT traffic that is coming to us, if it's coming to a port that we used to send outgoing traffic. This will allow you to see the response from the server, which you were dropping.
However, there's still a problem with DNS traffic, since it uses UDP not TCP. You can work around that by changing the first rule to:
iptables -P INPUT -p tcp DROP
so it only drops TCP traffic but not UDP traffic. There may be other ways to work around the DNS problem, depending on what exactly you want to do.
So your final ruleset should look like this:
iptables -P INPUT -p tcp DROP
iptables -I INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -i eth0 -p tcp --dport 22 -j ACCEPT
iptables -A INPUT -i eth0 -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -i eth0 -p tcp --dport 443 -j ACCEPT

IP tables catch xmas scans / null scans

im trying to use the below rules to can xmas scans and null scans however when testing I have checked my logs and unable to find the prefix?
iptables -A INPUT -p tcp --tcp-flags ALL ALL -j LOG --log-prefix "DROPPED XMAS PACKET:"
iptables -A INPUT -p tcp --tcp-flags ALL NONE -j LOG --log-prefix "DROPPED NULL PACKET:"
iptables -A INPUT -p tcp --tcp-flags ALL ALL -j DROP
iptables -A INPUT -p tcp --tcp-flags ALL NONE -j DROP
What have i got wrong or am i missing something ?
According to the Nmap man page, a Null scan would send a packet with no flags set, and a Xmas scan would send one with the FIN, PSH, and URG flags set. Your match for null scans looks like it should work, but your Xmas rule should be:
iptables -A INPUT -p tcp --tcp-flags ALL FIN,PSH,URG -j LOG --log-prefix "DROPPED XMAS PACKET:"
Also, these packets will not be part of an established TCP session, nor will they establish one. For that reason, it's possible that you have a rule earlier in your ruleset that is dropping these packets, since you are using -A (append) to add your rules.

Resources