Iptables command

From DD-WRT Wiki

(Difference between revisions)
Jump to: navigation, search
Revision as of 12:33, 22 March 2008 (edit)
Soulstace (Talk | contribs)
(Port Forwarding to a specific LAN IP)
← Previous diff
Revision as of 13:28, 22 March 2008 (edit) (undo)
Oaxley (Talk | contribs)
(Port Forwarding to a specific LAN IP)
Next diff →
Line 166: Line 166:
iptables -I FORWARD -p tcp -d 192.168.1.2 --dport 443 -j ACCEPT iptables -I FORWARD -p tcp -d 192.168.1.2 --dport 443 -j ACCEPT
-If you want to restrict the source IP (a question that is asked a lot on the forums), add ''-s 123.45.67.89'' to one of your rules (replacing the IP address with the real one of course). This should make it so only one IP address is able to access your forwarded port from the Internet.+If you want to restrict the source IP (a question that is asked a lot on the forums), add ''-s 123.45.67.89'' to one of your rules (replacing the IP address with the real one of course).
 + iptables -t nat -I PREROUTING -p tcp -s 123.45.67.89 -d $(nvram get wan_ipaddr) --dport 443 -j DNAT --to 192.168.1.2:443
 + iptables -I FORWARD -p tcp -d 192.168.1.2 --dport 443 -j ACCEPT
 +This should make it so only one IP address is able to access your forwarded port from the Internet.
====Deny access to a specific IP address==== ====Deny access to a specific IP address====

Revision as of 13:28, 22 March 2008

Iptables is a powerful administration tool for IPv4 packet filtering and NAT. It is used to set up, maintain, and inspect the tables of IP packet filter rules in the Linux kernel.

Iptables commands can be entered by command line interface, and/or saved as a Firewall script in the dd-wrt Administration panel. I tend to recommend testing and confirming your rules at the command line first. This way, if you happen to make a big mistake (like blocking access to the router), simply rebooting the router should repair it rather than having to do a hard reset. To get your rules to survive a reboot of the router, save them in a Firewall script as mentioned earlier.

I think we should have something about Firewall Builder on this page, since they're kind of related...

Contents

Basic Usage

iptables -[AD] chain rule-specification [options]
iptables -[RI] chain rulenum rule-specification [options]
iptables -D chain rulenum [options]
iptables -[LFZ] [chain] [options]
iptables -[NX] chain
iptables -E old-chain-name new-chain-name
iptables -P chain target [options]
iptables -h (print this help information)

Commands

--append -A chain     Append to chain
--delete  -D chain     Delete matching rule from chain
--delete  -D chain rulenum
                              Delete rule rulenum (1 = first) from chain
--insert  -I chain [rulenum]
                              Insert in chain as rulenum (default 1=first)
--replace -R chain rulenum
                              Replace rule rulenum (1 = first) in chain
--list      -L [chain]    List the rules in a chain or all chains
--flush   -F [chain]    Delete all rules in  chain or all chains
--zero    -Z [chain]   Zero counters in chain or all chains
--new    -N chain      Create a new user-defined chain
--delete-chain
             -X [chain]   Delete a user-defined chain
--policy  -P chain target
                              Change policy on chain to target
--rename-chain
             -E old-chain new-chain
                              Change chain name, (moving any references)

Options

--proto    -p [!] proto
                              protocol: by number or name, eg. `tcp'
--source  -s [!] address[/mask]
                              source specification
--destination  -d [!] address[/mask]
                              destination specification
--sport [!] port[:endport]
                              source port (use `:' when specifying range)
--dport [!] port[:endport]
                              destination port
--in-interface  -i [!] input name[+]
                              network interface name ([+] for wildcard)
--jump    -j target
                              target for rule (may load target extension)
--match  -m match
                              extended match (may load extension)
--state state
                              connection states to match: 
                                   INVALID NEW ESTABLISHED RELATED
--tcp-flags [!] mask 
                              match when the TCP flags are as specified:
                                   SYN ACK FIN RST URG PSH ALL NONE
--numeric    -n         numeric output of addresses and ports
--out-interface -o [!] output name[+]
                              network interface name ([+] for wildcard)
--table        -t table  table to manipulate (default: `filter')
--verbose   -v          verbose mode
--line-numbers         print line numbers when listing
--exact       -x          expand numbers (display exact values)
--fragment  -f          match second or further fragments only
--modprobe=<command>     try to insert modules using this command
--set-counters PKTS BYTES    set the counter during insert/append
--version    -V          print package version

MAC v1.3.7 options:
 --mac-source [!] XX:XX:XX:XX:XX:XX
                              Match source MAC address

Interfaces

When using the -i or -o to define the physical interfaces, remember that by default:
vlan0 is the 4 LAN ports
vlan1 is the WAN port
eth1 is the WIFI
br0 is a bridge connecting the 4 LAN and the WIFI together

Examples

I think examples are the best way to demonstrate the use of iptables.

Listing the rules in a chain

First I want to view the rules on my INPUT chain, this is the first chain traffic coming into my router will hit.

iptables -L INPUT

To get a little more detailed list, with actual IP numbers and packet data, I can do

iptables -L INPUT -nv

Then I might want to add a rule so that I can ssh into my router from a specific host/address outside. So I might type the following:

iptables -A INPUT -p tcp -s 150.100.whatever.something --dport 22 -j logaccept

So I am saying: Append to the INPUT chain a rule allowing protocol tcp, with a source of <my external IP that i want access from> traffic destined for port 22 on my router, jump to logaccept. I could have used -j ACCEPT which simply jumps to ACCEPT, but in this case I want to log it just to keep track so I use logaccept, which is a chain we have set up for this purpose.

Note: Simply adding a rule to the INPUT chain may not be enough to allow remote SSH access from the WAN. On some configurations, you must also Insert a PREROUTING rule for this to work properly. This is likely due to the router running Network Address Translation (NAT).

iptables -t nat -L
iptables -t nat -I PREROUTING -p tcp -m tcp --dport 22 -j DNAT --to-destination 192.168.1.1:22

Now if I type

iptables -L INPUT 

I see my shiny new rule appended to the INPUT chain. However, this is no good because in my case I have a rule blocking this traffic which occurs BEFORE the rule allowing it.

How do I change it? Simple.

First let's delete the rule we just made

iptables -L INPUT --line-numbers

will list the rules with their rule numbers. Let's say our rule is number 11

iptables -D INPUT 11   

Clearly this Deletes rule number 11 from the input chain.

Now instead of Appending I am going to Insert my rule into the number 1 position.

iptables -I INPUT -p tcp -s 150.100.whatever.something --dport 22 -j logaccept

So now rule number 1 is my new rule and the other rules have all shifted down a position.

If I wanted to change the IP address or any other aspect of my ssh rule I could use the -R (Replace) option and simply type in the new rule, ie

iptables -R INPUT 1 -p tcp -s 100.100.200.100 --dport 22 -j ACCEPT

This would replace rule number 1 on the INPUT chain with the new rule which has a new source IP address and jumps to ACCEPT instead of logaccept.

One more example: I want to run a mini web server on my router. Let's assume that it is already running on port 8000 and I can access it from the LAN side, but not from the WAN side. With

iptables -I INPUT -p tcp -d 192.168.1.1 --dport 8000 -j logaccept

the port 8000 will be opened. But I also have to setup NAT PREROUTING, so that the kernel forwards all packets on port 8000 from the outside to itself, 192.168.1.1:

iptables -t nat -I PREROUTING -p tcp -d $(nvram get wan_ipaddr) --dport 8000 -j DNAT --to 192.168.1.1:8000

Port Forwarding to a specific LAN IP

Port Forwarding can be accomplished from within the web interface here. However, the very same thing can be done a bit differently (tested and working), via command line. --u3gyxap: Example with port 443 and IP 192.168.1.2

iptables -t nat -I PREROUTING -p tcp -d $(nvram get wan_ipaddr) --dport 443 -j DNAT --to 192.168.1.2:443
iptables -I FORWARD -p tcp -d 192.168.1.2 --dport 443 -j ACCEPT

If you want to restrict the source IP (a question that is asked a lot on the forums), add -s 123.45.67.89 to one of your rules (replacing the IP address with the real one of course).

iptables -t nat -I PREROUTING -p tcp -s 123.45.67.89 -d $(nvram get wan_ipaddr) --dport 443 -j DNAT --to 192.168.1.2:443
iptables -I FORWARD -p tcp -d 192.168.1.2 --dport 443 -j ACCEPT

This should make it so only one IP address is able to access your forwarded port from the Internet.

Deny access to a specific IP address

iptables -I FORWARD -d 123.123.123.123 -j DROP

Which would DROP all packets to the given IP. Useful to block access to what not. If you want to log the entry when the IP is blocked you would set DROP to logdrop.

Deny access to a specific Outbound IP address with logging

iptables -I OUTPUT -d 239.255.255.250 -j logdrop

This becomes useful if there is a program that wants to gain an outbound connection to a specific address, but you don't want to allow the connection. In this specific example Windows uses this IP incorrectly as a broadcast address (search Google for more info). While viewing your router logs you will see Windows broadcast to this IP several times per minute. By default the router passes the broadcast and announces to everyone outside of your router that your PC exists. This rule will block this specific outbound IP and add an entry into the router log.

Block SMTP traffic except to specified hosts

Simple Mail Transfer Protocol operates on tcp port 25.

/usr/sbin/iptables -I FORWARD 1 -p tcp -d safe.server1.com --dport 25 -j logaccept
/usr/sbin/iptables -I FORWARD 2 -p tcp -d safe.server2.com --dport 25 -j logaccept
/usr/sbin/iptables -I FORWARD 3 -p tcp --dport 25 -j logdrop

Which would accept and log all smtp traffic to safe.server1.com and safe.server2.com, while blocking and dropping all other outgoing smtp traffic.

Allow HTTP traffic only to specific domain(s)

Similarly, we can use the above method to filter other ports and protocols as well, such as standard web traffic operating on tcp port 80.

iptables -I FORWARD 1 -p tcp -d dd-wrt.com --dport 80 -j ACCEPT
iptables -I FORWARD 2 -p tcp --dport 80 -j DROP

Which would accept all http traffic to dd-wrt.com, while blocking outgoing http traffic to anywhere else. If you wish to allow multiple sites, insert additional rules before the DROP (making sure to order and number them correctly).

Block all traffic except HTTP HTTPS and FTP

This example blocks everything except our normal web traffic, encrypted (ssl), and the file transfer protocol.

iptables -I FORWARD 1 -p tcp -m multiport --dport 21,80,443 -j ACCEPT
iptables -I FORWARD 2 -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -I FORWARD 3 -j DROP

Caution! Users are still able to get through the firewall if they are sly enough to change port numbers of their P2P or other application. In that case, you should consider using Access Restrictions to mitigate the possibility of that happening.

Restrict access by MAC address

In this example, we will demonstrate how to restrict access to the router's web interface by MAC address. In other words, only the computer having the specified MAC address should be able to access the web interface from the LAN.

First, if there are no Access Restrictions policies enabled and filtering by MAC addresses, you may need to insert the iptables mac module manually:

insmod ipt_mac
iptables -I INPUT -p tcp --dport 80 -m mac ! --mac-source 00:12:34:56:78:9A -j REJECT --reject-with tcp-reset

Notice the ! (bang) which is another new concept introduced here. It means "NOT". So, by inspecting the rule closely, we see that it will REJECT packets destined to port 80 of the router so long as they do NOT originate from our computer with the desired MAC address.

Caution! As usual when dealing with MAC addresses, be aware that it is possible for malicious user(s) to spoof their MAC address with that of a trusted machine. You can help combat this by use of static ARP entries, VLANs, etc.

Modifying the TTL

The Time To Live is the maximum number of routers a packet will travel through before it is discarded. In certain situations, it may prove useful to modify it in order to make your network more reliable.

  • Example 1: Set the incoming TTL to 10, before the router routes it into the LAN
iptables -t mangle -I PREROUTING -i vlan1 -j TTL --ttl-set 10
  • Example 2: Set the outgoing TTL to 128, just as if a Windows machine was connected directly to the modem.
iptables -t mangle -I POSTROUTING -o vlan1 -j TTL --ttl-set 128
  • Example 3: Try to hide the fact that an outgoing packet was routed, by incrementing the TTL by one.
iptables -t mangle -I POSTROUTING -o vlan1 -j TTL --ttl-inc 1

See Also

One-to-one NAT
Port Blocking

External Resources

http://linux.die.net/man/8/iptables
http://www.iptables.org/documentation/HOWTO//packet-filtering-HOWTO-7.html
http://www.iptables.org/documentation/HOWTO//netfilter-hacking-HOWTO.html