# IPTABLES Desperate need of Help!!!! Please

## cowboy0629

Hi all I'm really new to Gentoo as most of you probably already know... My Gateway/Firewall is finally up and running but I have now ran into another problem.. and I don't know how to fix them

WAN = enp0s25 --> PPPOE BELL MODEM {BRIDGE MODE} ----> Internet

LAN = Internal Network

Because I have a fairly powerful computer running my gateway.. I decided to put my WEB Server and SSHD on it

Now using this Iptables script I could access Gateway from my friends house using SSH as well as my WebServer <apache2>

but none of my household computers could reach the outside world I could access all computers inside

```

### This *has* to be loaded, or no NAT!!!

modprobe ipt_MASQUERADE

#WAN (eth0=enp0s25) --> Outside Network

#export WAN="enp0s25"

WAN="ppp0"

#LAN (eth1=enp17s0) --> Inside Network

LAN="enp17s0"

#Flush current rules

iptables -F

iptables -t nat -F

iptables -X

### Always need these 3:

echo 1 > /proc/sys/net/ipv4/ip_forward

for f in /proc/sys/net/ipv4/conf/*/rp_filter ; do echo 1 > $f ; done

iptables -t nat -A POSTROUTING -o ppp0 -j MASQUERADE

iptables -t nat -A POSTROUTING -o enp0s25 -j MASQUERADE

iptables -t nat -A POSTROUTING -o enp17s0 -j MASQUERADE

#iptables -I FORWARD 1 -o ppp0 -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --set-mss 1412

#Setup default policies to handle unmatched traffic

#iptables -P INPUT ACCEPT

#iptables -P OUTPUT ACCEPT

#iptables -P FORWARD DROP

#Locks Services so they only work from the LAN

#iptables -I INPUT 1 -i ${LAN} -j ACCEPT

#iptables -I INPUT 1 -i lo -j ACCEPT

#iptables -A INPUT -p UDP --dport bootps ! -i ${LAN} -j REJECT

#iptables -A INPUT -p UDP --dport domain ! -i ${LAN} -j REJECT

#Allow access to the ssh server from the WAN

#iptables -A INPUT -p TCP --dport ssh -i ${WAN} -j ACCEPT

#Drop TCP/UDP packets to privleged Ports:

#iptables -A INPUT -p TCP ! -i ${LAN} -d 0/0 --dport 0:1023 -j DROP

#iptables -A INPUT -p UDP ! -i ${LAN} -d 0/0 --dport 0:1023 -j DROP

#Add NAT Rules

#iptables -I FORWARD -i ${LAN} -d 192.168.0.0/255.255.255.0 -j DROP

#iptables -A FORWARD -i ${LAN} -s 192.168.0.0/255.255.255.0 -j ACCEPT

#iptables -A FORWARD -i ${WAN} -d 192.168.0.0/255.255.255.0 -j ACCEPT

#Port Forwarding

# (Forward Outside to GW2)

#iptables -t nat -A PREROUTING -p tcp --dport 28 -i ${WAN} -j DNAT --to 192.168.0.101

#iptables -t nat -A PREROUTING -p tcp --dport 80 -i ${WAN} -j DNAT --to 192.168.0.121

#Xbox Live (Rules for my XboxOne and Xbox360)

#iptables -t nat -A PREROUTING -p udp --dport 88 -i ${WAN} -j DNAT --to 192.168.0.102

#iptables -t nat -A PREROUTING -p tcp --dport 3074 -i ${WAN} -j DNAT --to 192.168.0.102

#iptables -t nat -A PREROUTING -p udp --dport 3074 -i ${WAN} -j DNAT --to 192.168.0.102

##iptables -t nat -A PREROUTING -p tcp --dport 53 -i ${WAN} -j DNAT --to 192.168.0.102

##iptables -t nat -A PREROUTING -p udp --dport 53 -i ${WAN} -j DNAT --to 192.168.0.102

##iptables -t nat -A PREROUTING -p tcp --dport 80 -i ${WAN} -j DNAT --to 192.168.0.102

##iptables -t nat -A PREROUTING -p udp --dport 500 -i ${WAN} -j DNAT --to 192.168.0.102

#iptables -t nat -A PREROUTING -p udp --dport 3544 -i ${WAN} -j DNAT --to 192.168.0.102

#iptables -t nat -A PREROUTING -p udp --dport 4500 -i ${WAN} -j DNAT --to 192.168.0.102

#Instruct the IPtables daemon to save the changes to the rules

### THESE are the rules. You can save them if you want, but every time you alter these rules,

### or change interfaces, you will have to save them again.

#/etc/init.d/iptables save

```

Now with this Iptables scripte All my Computers get access to the Internet and everything internal works including SSH and webserver... But I cannot get in from the outside world ... can someone please tell me what I need to add or change to be able to get to SSH and HTTP server etc from the internet on my gateway machine.. please... I have been over a month now trying to get this thing working properly and pulling my hair out

```

#!/bin/bash

#

### This *has* to be loaded, or no NAT!!!

modprobe ipt_MASQUERADE

#WAN (eth0=enp0s25) --> Outside Network

#export WAN="enp0s25"

export WAN="ppp0"

#LAN (eth1=enp17s0) --> Inside Network

export LAN="enp17s0"

#Flush current rules

iptables -F

iptables -t nat -F

iptables -X

#Setup default policies to handle unmatched traffic

iptables -P INPUT ACCEPT

iptables -P OUTPUT ACCEPT

iptables -P FORWARD DROP

#Locks Services so they only work from the LAN

iptables -I INPUT 1 -i ${LAN} -j ACCEPT

iptables -I INPUT 1 -i lo -j ACCEPT

iptables -A INPUT -p UDP --dport bootps ! -i ${LAN} -j REJECT

iptables -A INPUT -p UDP --dport domain ! -i ${LAN} -j REJECT

#Allow access to the ssh server from the WAN

iptables -A INPUT -p TCP --dport ssh -i ${WAN} -j ACCEPT

#Drop TCP/UDP packets to privleged Ports:

iptables -A INPUT -p TCP ! -i ${LAN} -d 0/0 --dport 0:1023 -j DROP

iptables -A INPUT -p UDP ! -i ${LAN} -d 0/0 --dport 0:1023 -j DROP

#Add NAT Rules

iptables -I FORWARD -i ${LAN} -d 192.168.0.0/255.255.255.0 -j DROP

iptables -A FORWARD -i ${LAN} -s 192.168.0.0/255.255.255.0 -j ACCEPT

iptables -A FORWARD -i ${WAN} -d 192.168.0.0/255.255.255.0 -j ACCEPT

iptables -t nat -A POSTROUTING -o ${WAN} -j MASQUERADE

#Port Forwarding

# (Forward Outside to GW2)

#iptables -t nat -A PREROUTING -p tcp --dport 28 -i ${WAN} -j DNAT --to 192.168.0.101

#iptables -t nat -A PREROUTING -p tcp --dport 80 -i ${WAN} -j DNAT --to 192.168.0.121

#Xbox Live (Rules for my XboxOne and Xbox360)

iptables -t nat -A PREROUTING -p udp --dport 88 -i ${WAN} -j DNAT --to 192.168.0.102

iptables -t nat -A PREROUTING -p tcp --dport 3074 -i ${WAN} -j DNAT --to 192.168.0.102

iptables -t nat -A PREROUTING -p udp --dport 3074 -i ${WAN} -j DNAT --to 192.168.0.102

#iptables -t nat -A PREROUTING -p tcp --dport 53 -i ${WAN} -j DNAT --to 192.168.0.102

#iptables -t nat -A PREROUTING -p udp --dport 53 -i ${WAN} -j DNAT --to 192.168.0.102

#iptables -t nat -A PREROUTING -p tcp --dport 80 -i ${WAN} -j DNAT --to 192.168.0.102

#iptables -t nat -A PREROUTING -p udp --dport 500 -i ${WAN} -j DNAT --to 192.168.0.102

iptables -t nat -A PREROUTING -p udp --dport 3544 -i ${WAN} -j DNAT --to 192.168.0.102

iptables -t nat -A PREROUTING -p udp --dport 4500 -i ${WAN} -j DNAT --to 192.168.0.102

#Inform the kernel that IP forwarding is OK:

echo 1 > /proc/sys/net/ipv4/ip_forward

for f in /proc/sys/net/ipv4/conf/*/rp_filter ; do echo 1 > $f ; done

#Instruct the IPtables daemon to save the changes to the rules

### THESE are the rules. You can save them if you want, but every time you alter these rules,

### or change interfaces, you will have to save them again.

/etc/init.d/iptables save

```

thanks in advance.... 

 Mike Dennison

----------

## cowboy0629

Got My SSH Sever and HTTP Server working on the outside world.. but am wondering if I did it the proper way or not...???

So I removed this from my script

```

#Allow access to the ssh server from the WAN

#iptables -A INPUT -p TCP --dport ssh -i ${WAN} -j ACCEPT

```

and added this in its place

```

iptables -A OUTPUT -p tcp --sport 28 -j ACCEPT

iptables -A OUTPUT -p tcp --sport 80 -j ACCEPT

```

is this the right way to do this? is there a better way to do this? or did I just open my Gateway/Firewall/Server up for attacks by doing it this way?

Thanks

 Mike Dennison

----------

## ct85711

well, any ports that you open is a potential attack vector. One way to help reduce the threat, is by configuring the services to use a non-standard port number; like for ssh, instead of using 22, set it to listen on say 2260.

 *Quote:*   

> iptables -A OUTPUT -p tcp --sport 28 -j ACCEPT 

 

Now, I am assuming you was intending this rule for ssh, though the default port for ssh is 22, not 28.

----------

## cowboy0629

 *ct85711 wrote:*   

> .
> 
>  *Quote:*   iptables -A OUTPUT -p tcp --sport 28 -j ACCEPT  
> 
> Now, I am assuming you was intending this rule for ssh, though the default port for ssh is 22, not 28.

 

Yes that 8s my rule for ssh..  I changed my sshd_config  and   ssh_config files to use port 28

Thanks

 Mike Dennison

----------

## cboldt

You have a bit of a mishmash of variable assignments and usage, which I won't get into.  But I'll show how to configure iptables to get incoming ssh to your machine.

I notice too, you might be overlooking the fact that some of the lines you are deleting and rearranging have no effect anyway.  Lines started with the hash (#) symbol are merely comments.

When you removed "#iptables -A INPUT -p TCP --dport ssh -i ${WAN} -j ACCEPT", that had no effect at all.

What you need in order to have connections from the outside, destined for your ssh daemon, is to allow NEW packets headed for port 28 (your pick of port assignment) to be routed to whichever machine will field ssh connection requests.  If the router machine is the one handling ssh, then you want to allow these packets with an INPUT rule, not an OUTPUT rule.

Separately from that, iptables should also be configured to allow ESTABLISHED traffic to run, without first passing through a bunch of iptables tests.

```
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
```

As an aside, if you put this command early in your script, the rule will be near the top of your INPUT firewall chain.  I learned, late in my tinkering with iptables, that one can use "-I" (insert) instead of "-A" (append), and the rule is inserted either at the top (default) or in a specified numerical position in the firewall chain.  Generically, keep in mind that the final firewall chains don't necessarily have the same order of links as the order of link creation in your firewall building script.

To allow traffic destined for port 28 on the firewall/router machine, you would use this command ...

```
iptables -A INPUT -p tcp --dport 28 -j ACCEPT
```

You can narrow that rule to allow only --dport 28 hitting the ${WAN} interface hardware, or only the ${LAN} interface hardware, but I think you do NOT want to do that.

The "--dport ssh" form substitutes the standard ssh port number, 22, for "ssh".  You can use variables here too.  I use a non-standard ssh port, and define ${SSHD_PORT} at the top of my firewall building script

----------

## Hu

cboldt provided some good critiques of your specific choices.

In general, I recommend against using a bash script to load iptables rules, because you load the rules one at a time, and if any of them fail, they will print an error on stderr, and later rules will load anyway.  This can easily leave you in a situation that works very differently from the ones you would have gotten if (1) the script never ran or (2) the script ran to completion successfully.  I recommend that, instead of using a bash script, you load rules via iptables-restore.  This will either succeed or fail atomically.  If you have a complex ruleset that might fail (such as if it relies on optional kernel features), you can load two rulesets.  First, load a simple ruleset that will not fail to load, but is either fail-open or fail-closed depending on your needs.  I like fail-closed, since it is more likely to draw my attention to the problem.  Next, load the full ruleset.  If it succeeds, it replaces the simple ruleset.  If it fails, your filters are in a suboptimal but good state until an administrator fixes the problem.

You can still use a bash wrapper if you need to set other values, such as your sysctl changes.  If you always need NAT loaded on this machine, why not make it built-in so that you do not need to modprobe it?

Using MASQUERADE on traffic headed into the LAN is weird.  This should be unnecessary, and will likely be confusing later on.  What failures did you see when you did not have this rule?

You posted two separate scripts, neither of which does everything you want.  Which one do you want us to debug?

----------

## Ant P.

Using iptables-restore would be correct, but the device name bash variables would have to go away. The traditional way to set up a NAT router would be to use "ppp+" as the device name which acts as a wildcard for the number on the end; I'm not sure how that'd work with Predictably-Randomized Interface Names.

----------

## Hu

He could use a script that generates a ruleset in the style that iptables-restore consumes, then run iptables-restore with its stdin redirected to the generated ruleset.  I use this technique on a system where some of the rules depend on non-static data beyond my control (e.g. DHCP-assigned IP address).  I use the Gentoo initscript to load the simple ruleset to put the system into a safe default, then a later stage script computes the dynamic ruleset and pipes it to iptables-restore.

----------

## cowboy0629

I am working with the 2nd one.. now with the changes suggest above.... So I don't need the MASQ on what card LAN?

basically my rules are the ones that came from the site Gentoo Home Router

----------

## cowboy0629

cboldt

Thanks Here is what I did .... 

```

#Allow access to the ssh server from the WAN

iptables -A INPUT -p tcp --dport ${SSHD_PORT} -j ACCEPT

#Apache WebServer Rules

iptables -A INPUT -p tcp --dport ${HTTP_PORT} -j ACCEPT

```

SSHD and HTTP everything seems to be working here now... I also added the other line.. hopefully I put it in the right spot

```

#Setup default policies to handle unmatched traffic

iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

iptables -P INPUT ACCEPT

iptables -P OUTPUT ACCEPT

iptables -P FORWARD DROP

```

I use "#" to take take lines out of the script in case I want to put things back the way they where or until I am done making my changes and get things working.. I do understand they are still there but I understand they are not in use because of the "#"

for Code set # 2 is this where you wanted me to put this.. and this Line allows connections that are established to keep running without using the iptables?

----------

## cowboy0629

 *Hu wrote:*   

> cboldt provided some good critiques of your specific choices.
> 
> In general, I recommend against using a bash script to load iptables rules, because you load the rules one at a time, and if any of them fail, they will print an error on stderr, and later rules will load anyway.  This can easily leave you in a situation that works very differently from the ones you would have gotten if (1) the script never ran or (2) the script ran to completion successfully.  I recommend that, instead of using a bash script, you load rules via iptables-restore.  This will either succeed or fail atomically.  If you have a complex ruleset that might fail (such as if it relies on optional kernel features), you can load two rulesets.  First, load a simple ruleset that will not fail to load, but is either fail-open or fail-closed depending on your needs.  I like fail-closed, since it is more likely to draw my attention to the problem.  Next, load the full ruleset.  If it succeeds, it replaces the simple ruleset.  If it fails, your filters are in a suboptimal but good state until an administrator fixes the problem.
> 
> You can still use a bash wrapper if you need to set other values, such as your sysctl changes.  If you always need NAT loaded on this machine, why not make it built-in so that you do not need to modprobe it?
> ...

 

I have  no Idea how to use the ip-restore...

this is my first month of using gentoo and linux so it is still a learning game for me I have a friend that has been using Linux/Gentoo for a long time but he can't always help.. I have dived into way deeper then him right off the bat.. I no longer use Windows any more I figure if I am going to make the jump I am going to do it and get it over with.. I come here for help after I have read and read and can't figure it out on my own and when my friend cant help me.. he told me to use a script so I could change things and if they don't work I can change it back to a working state quickly before anyone knows I did it.. I have a fairly large internal network where people get upset when their Internet connection or Netflix quits working.. 

If iptables-restore is the proper way to do it.. maybe I should learn how.. can you point me in the right direction but as fair as I know the bash table is the quicker then typing all the rules one by one to change them...

----------

## cowboy0629

I have noticed in my script file

that in some of my rules stuff is defined in capital and some stuff in lower case for instance

```

#Allow access to the ssh server from the WAN

iptables -A INPUT -p tcp --dport ${SSHD_PORT} -j ACCEPT

#Apache WebServer Rules

iptables -A INPUT -p tcp --dport ${HTTP_PORT} -j ACCEPT

#Drop TCP/UDP packets to privleged Ports:

iptables -A INPUT -p TCP ! -i ${LAN} -d 0/0 --dport 0:1023 -j DROP

iptables -A INPUT -p UDP ! -i ${LAN} -d 0/0 --dport 0:1023 -j DROP

```

TCP & UDP in places are capital and other places lowercase... I know capitals and lowercase makes a difference in Linux... so should I change all the capital TCP & UDP to lowercase or does this matter

Also Thank-you everyone for your help and comments they are really helping me[/b]

Mike Dennison

----------

## cboldt

I assume you defined the variable SSHD_PORT=28 somewhere!  You don't need to define the HTTP_PORT if you use the standard value of 80, you can use "--dport 80" (obviously), or "--dport http".  Port number to port name assignments are established in the file /etc/services.  The only reasons I create and use a SSHD_PORT variable are that the iptables sshd defining lines are pretty deep in my script, in a subroutine (so setting the value at the top is a convenience), and the value appears in a few lines.  Because the value is in a few lines, and it is a nonstandard port, there is a risk over the long run that I'd change a port number in one place and overlook others.

You ask if uppercase/lowercase makes a difference in the protocol assignment switch.  Usually (as will be explained), that particular switch is not case sensitive, but the iptables man page gives all of the available options in lowercase (The  specified  protocol  can  be  one  of  tcp,  udp,  udplite,  icmp, icmpv6, esp, ah, sctp, mh or the special keyword "all", or it can be a numeric value, representing one of these protocols or a different one.  A protocol name from /etc/protocols is also allowed.)

The file /etc/protocols file includes protocol names and protocol aliases.  Look at /etc/protocols.  Notice the uppercase aliases.  It is only because of this aliases that uppercase works at all.  iptables does a resaonably good job of giving error messages, try using a protocol name that is -NOT- defined and is -NOT- an alias, somewhere in your script, and see what happens.  Use a typo, or mixed case, like TcP, or PCP.

This "all uppercase/all lowercase" indifference on the "-p" switch is exceptional.  When in doubt, follow the instructions and examples.  I have defined names of certain chains (like "priority" and "bad-flags"), and those have to be matched exactly, case sensitive.  One could use mixed case.

You also asked in the -m conntrack --ctstate ESTABLISHED,RELATED line is in the right place.  It's "close enough," but you don't give enough context for me to say for sure.  The "-P" (uppercase pee) switch sets policy, which is an entirely different function compared with establishing a rule.  The POLICY is what happens to a packet that matches zero rules.

The order that I have for the rules in my INPUT chain is to first allow everything on the local interface ...

```
iptables -A INPUT    -i lo -j ACCEPT
```

The rules for ESTABLISHED,RELATED packets follow immediately after that.

```
iptables -A INPUT    -p tcp                  -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

iptables -A INPUT    -p udp                  -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

iptables -A INPUT    -p icmp                 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
```

I could (maybe should) simplify that to one rule, using "-p all".  Under the firewall running here, packets that aren't of one of the three listed protocols (tcp, udp, icmp) but are ESTABLISHED,RELATED, will be logged.

The point I want you to take away though is that the iptables rule should give a VERY short matching path to local (not on ANY network, not on the local network, but within the machine) traffic.

With regard to iptables-save and iptables-restore, you can safety type `iptables-save` at any time (or `iptables-save | less` so you can scroll through it).  The current ruleset will be printed on your screen.  You will see that it sort of resembles your script.  When you have a working firewall, saving and restoring it using the iptables-save form is by far best.  BY FAR.  Not just for speed reasons.

But one thing at a time.  I sense that you have your hands more than full just figuring out how to create a firewall.

Not that using iptables-save and iptables-restore is difficult, just that it is a totally separate activity from creating a decent firewall in the first place (pretty difficult when hand-crafted).

iptables-save > /var/lib/iptables/iptables.rules        # saves the rules into a file

iptables-restore -c /var/lib/iptables/iptables.rules   # creates a firewall from the saved rules file

Edited to correct `iptables | less` to `iptables-save | less`

----------

## cowboy0629

cboldt

Thankyou for the explanation... Im reading the man and a few other pages to try to get the hang of the process but your help  us a great help so far.. and greatly appreciated.. I hope someday I will get the ability to help or return the favor.. I like using varibles in the script makes it allot easier to change things once they get larger..

Here is a copy of iptables-save |less

if yourself or anyone see anything that is wrong or should be added or removed or changed please don't hesitate to let me know....

```

# Generated by iptables-save v1.6.0 on Sun Jun 26 22:26:47 2016

*filter

:INPUT ACCEPT [365495:85271225]

:FORWARD DROP [0:0]

:OUTPUT ACCEPT [182911802:476317371208]

-A INPUT -i lo -j ACCEPT

-A INPUT -i enp17s0 -j ACCEPT

-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT

-A INPUT ! -i enp17s0 -p udp -m udp --dport 67 -j REJECT --reject-with icmp-port-unreachable

-A INPUT ! -i enp17s0 -p udp -m udp --dport 53 -j REJECT --reject-with icmp-port-unreachable

-A INPUT -p tcp -m tcp --dport 28 -j ACCEPT

-A INPUT -p tcp -m tcp --dport 80 -j ACCEPT

-A INPUT ! -i enp17s0 -p tcp -m tcp --dport 0:1023 -j DROP

-A INPUT ! -i enp17s0 -p udp -m udp --dport 0:1023 -j DROP

-A FORWARD -d 192.168.0.0/24 -i enp17s0 -j DROP

-A FORWARD -s 192.168.0.0/24 -i enp17s0 -j ACCEPT

-A FORWARD -d 192.168.0.0/24 -i ppp0 -j ACCEPT

COMMIT

# Completed on Sun Jun 26 22:26:47 2016

# Generated by iptables-save v1.6.0 on Sun Jun 26 22:26:47 2016

*nat

:PREROUTING ACCEPT [285577:63016554]

:INPUT ACCEPT [196012:52203418]

:OUTPUT ACCEPT [7109:480688]

:POSTROUTING ACCEPT [43:6585]

-A PREROUTING -i ppp0 -p udp -m udp --dport 88 -j DNAT --to-destination 192.168.0.102

-A PREROUTING -i ppp0 -p tcp -m tcp --dport 3074 -j DNAT --to-destination 192.168.0.102

-A PREROUTING -i ppp0 -p udp -m udp --dport 3074 -j DNAT --to-destination 192.168.0.102

-A PREROUTING -i ppp0 -p udp -m udp --dport 3544 -j DNAT --to-destination 192.168.0.102

-A PREROUTING -i ppp0 -p udp -m udp --dport 4500 -j DNAT --to-destination 192.168.0.102

-A POSTROUTING -o ppp0 -j MASQUERADE

COMMIT

# Completed on Sun Jun 26 22:26:47 2016

```

 *Quote:*   

> Code:	
> 
> iptables -A INPUT    -p tcp                  -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
> 
> iptables -A INPUT    -p udp                  -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
> ...

 

So what or where should I put these items.. I am going to post my most recent script file to update everyone on what I have going on now

thanks again in advance 

 Mike D

----------

## cowboy0629

```

#!/bin/bash

#

#       JUNE 26 2016

#

### This *has* to be loaded, or no NAT!!!

modprobe ipt_MASQUERADE

#WAN (eth0=enp0s25) --> Outside Network

#export WAN="enp0s25"

export WAN="ppp0"

#LAN (eth1=enp17s0) --> Inside Network

export LAN="enp17s0"

#Other Varibles

export SSHD_PORT="28"

export HTTP_PORT="80"

#Flush current rules

iptables -F

iptables -t nat -F

iptables -X

#Setup default policies to handle unmatched traffic

iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

iptables -P INPUT ACCEPT

iptables -P OUTPUT ACCEPT

iptables -P FORWARD DROP

#Locks Services so they only work from the LAN

iptables -I INPUT 1 -i ${LAN} -j ACCEPT

iptables -I INPUT 1 -i lo -j ACCEPT

iptables -A INPUT -p udp --dport bootps ! -i ${LAN} -j REJECT

iptables -A INPUT -p udp --dport domain ! -i ${LAN} -j REJECT

#Allow access to the ssh server from the WAN

iptables -A INPUT -p tcp --dport ${SSHD_PORT} -j ACCEPT

#Apache WebServer Rules

iptables -A INPUT -p tcp --dport ${HTTP_PORT} -j ACCEPT

#Drop TCP/UDP packets to privleged Ports:

iptables -A INPUT -p tcp ! -i ${LAN} -d 0/0 --dport 0:1023 -j DROP

iptables -A INPUT -p udp ! -i ${LAN} -d 0/0 --dport 0:1023 -j DROP

#Add NAT Rules

iptables -I FORWARD -i ${LAN} -d 192.168.0.0/255.255.255.0 -j DROP

iptables -A FORWARD -i ${LAN} -s 192.168.0.0/255.255.255.0 -j ACCEPT

iptables -A FORWARD -i ${WAN} -d 192.168.0.0/255.255.255.0 -j ACCEPT

iptables -t nat -A POSTROUTING -o ${WAN} -j MASQUERADE

#Port Forwarding

# (Forward Outside to GW2)

#iptables -t nat -A PREROUTING -p tcp --dport 28 -i ${WAN} -j DNAT --to 192.168.0.101

#iptables -t nat -A PREROUTING -p tcp --dport 80 -i ${WAN} -j DNAT --to 192.168.0.121

#Xbox Live (Rules for my XboxOne and Xbox360)

iptables -t nat -A PREROUTING -p udp --dport 88 -i ${WAN} -j DNAT --to 192.168.0.102

iptables -t nat -A PREROUTING -p tcp --dport 3074 -i ${WAN} -j DNAT --to 192.168.0.102

iptables -t nat -A PREROUTING -p udp --dport 3074 -i ${WAN} -j DNAT --to 192.168.0.102

#iptables -t nat -A PREROUTING -p tcp --dport 53 -i ${WAN} -j DNAT --to 192.168.0.102

#iptables -t nat -A PREROUTING -p udp --dport 53 -i ${WAN} -j DNAT --to 192.168.0.102

#iptables -t nat -A PREROUTING -p tcp --dport 80 -i ${WAN} -j DNAT --to 192.168.0.102

#iptables -t nat -A PREROUTING -p udp --dport 500 -i ${WAN} -j DNAT --to 192.168.0.102

iptables -t nat -A PREROUTING -p udp --dport 3544 -i ${WAN} -j DNAT --to 192.168.0.102

iptables -t nat -A PREROUTING -p udp --dport 4500 -i ${WAN} -j DNAT --to 192.168.0.102

#Inform the kernel that IP forwarding is OK:

echo 1 > /proc/sys/net/ipv4/ip_forward

for f in /proc/sys/net/ipv4/conf/*/rp_filter ; do echo 1 > $f ; done

#Instruct the IPtables daemon to save the changes to the rules

/etc/init.d/iptables save

```

Xbox rules.. I need to work with multiple xbox's on network but not really concerned about that yet unless someone knows what to do...

----------

## cboldt

```
iptables -I INPUT 1 -i ${LAN} -j ACCEPT

iptables -I INPUT 1 -i lo -j ACCEPT 
```

The effect of those is to first insert the rule to ACCEPT everything coming into the $LAN hardware interface (more on this shortly), then insert above that, a rule that ACCEPTS everything on the local (machine internal) interface.

There is nothing wrong in principle with inserting one rule above the other, but it is more conventional when building a firewall, to write the rules in the same order they will be tested.  Again, no problem with the style, just be aware of the effect (which you get to see with `iptables-save` anyway).  Also, because you are inserting the rules 'at the top of the chain," you can omit the numerical reference.  "-I 1" is exactly the same as "-I".

Substantively, the "iptables -I INPUT 1 -i ${LAN} -j ACCEPT" rule accepts EVERYTHING coming into the $LAN interface, so no later rule affecting the $LAN interface will ever come into play.  You do NOT want this, I see later rules that aim to DROP certain packets coming into the $LAN hardware interface.  Get rid of "iptables -I INPUT 1 -i ${LAN} -j ACCEPT".

Somewhat related, the policy you have on INPUT is to accept packets, so packets that don't match a rule (which might be numerous) are coming in.  This may be what you want.  I do similar by having the LAST rules in my chain accept everything that comes through the rest of the rules.  In other words, the policy is DROP, but since I have a rule that accepts everything, the policy only plays when those rules are removed.  However, those final rules in my INPUT chain also LOG the packets, so I can see a record of every TCP and UDP packet that does not match a rule.  I use this approach to monitor network traffic as machines and services are added to the network.

```
iptables -A INPUT -p tcp ! -i ${LAN} -d 0/0 --dport 0:1023 -j DROP

iptables -A INPUT -p udp ! -i ${LAN} -d 0/0 --dport 0:1023 -j DROP 
```

Those rules have the effect of DROPping only packets that are -NOT- coming into the $LAN interface.  This may be what you want.  But, having only the two external hardware interfaces ($LAN and $WAN), I'd rephrase this so it is clear that the firewall is dropping port 0:1023 traffic from $WAN, instead of dropping port 0:1023 traffic from "not $LAN."

Same principle applies to the rules for packets destined for ports 67 and 53.

You use a number of "-m udp" and "-m tcp" switches.  I don't know the effect of those, and think they are not necessary.

I haven't deployed a NAT and FORWARD firewall in years, so can't offer any criticism or agreement with the structure of that part of your firewall.

Edit to add a remark about the "-m conntrack ... RELATED,ESTABLISHED" line.  You are all set on that.  You have one rule that covers all protocols, and that rule is located appropriately in the chain.  Just to explain the difference between what you have and what I showed earlier, I have three rules there, one for each protocol (tcp, udp, and icmp) vs. you have one rule that covers all protocols.  The method I showed is less efficient than the method you are using, and for accepting RELATED.ESTABLISHED packets, I can't think of any reason or advantage to have separate rules, protocol by protocol.

----------

## Syl20

 *cowboy0629 wrote:*   

> 
> 
> ```
> #Setup default policies to handle unmatched traffic
> 
> ...

 

Ouch.

First, you should avoid writing "iptables -A" (append) rules before "iptables -P" (default policy) ones. Not really a problem, but it's better to separate the default policy rules from the others, for readability reasons.

Second, defining a default policy to "ACCEPT" is awful, even more for the INPUT chain. That means your firewall will accept all the connections you didn't explicitely forbid (black list), instead of dropping all you didn't explicitely accept (white list). At worst, end your rules set with a generic DROP rule. And you can add some logging rules to know what is rejected :

```
# Final drop

iptables -A INPUT -j LOG --log-prefix "IPTABLES final INPUT drop : "

iptables -A INPUT -j DROP

iptables -A FORWARD -j LOG --log-prefix "IPTABLES final FORWARD drop : "

iptables -A FORWARD -j DROP

iptables -A OUTPUT -j LOG --log-prefix "IPTABLES final OUTPUT drop : "

iptables -A OUTPUT -j DROP

#Inform the kernel that IP forwarding is OK:

echo 1 > /proc/sys/net/ipv4/ip_forward

for f in /proc/sys/net/ipv4/conf/*/rp_filter ; do echo 1 > $f ; done

#Instruct the IPtables daemon to save the changes to the rules

/etc/init.d/iptables save 
```

 *Quote:*   

> 
> 
> ```
> iptables -I INPUT 1 -i ${LAN} -j ACCEPT
> 
> ...

 

Even if that can be useful in some cases, you should avoid mixing "iptables -I" (insert, i.e. "put the rule on the first position in the chain") and "iptables -A" (append, i.e. "put the rule on the last position in the chain". One more time, that's not really a problem, but that makes the script a lot more difficult to read. Prefer using append rules only, unless you really can't.

Keep in mind that, for each packet it intercepts, netfilter reads the rules, one by one, on the defined order (so the -I and the -A options are important), until the packet mathes one. Then it applies this rule, and, unless the rule target is "LOG", it stops there. So it doesn't read the next rules.

 *Quote:*   

> 
> 
> ```
> #Drop TCP/UDP packets to privleged Ports:
> 
> ...

 

If you define a DROP default policy, these rules are useless.

 *Quote:*   

> 
> 
> ```
> #Add NAT Rules
> 
> ...

 

These rules are not NAT rules.  :Wink: 

----------

## cowboy0629

Does anyone have a good set of rules that I can use.. or see.. I am really confused right now.. the rules I am using are the ones from Gentoo/Home Router and something happend last night when I went thru and changed the capital UDP and TCP to lower case.;. the hole network went down and I could not get it up and running again until I did a modem reboot and changed them back to capitals.. it also seems that these tables are very bad.. because allot of changes I try to make to them.. it locks my internal network off the network.. I am not sure where to start.. I had a friend try to fix them up for me and then I lost internet... I don't know what is going on...

here is the guide I used to make the router and it shows the iptables I used to get started.. I've been reading.. and also been told that iptables are easy once I get to know how to use them properly but.. Im pulling my hear out.. .for instance when I changed the capital UDP and TCP to lowercase.. my ping times to google went for 10ms to 3000  - 4000ms... I am afraid to change things around in case it locks everything out again.. I do want my network to work.. and my friend setup port sentry for me but it is not logging anything either.. 

would it be easier if I made a user account so someone could ssh and see whats going on..

Here is the site I used to build my router/firewall   https://wiki.gentoo.org/wiki/Home_Router

----------

## albright

I guess you want to learn iptables, but why not just use shorewall (or equivalent)?

----------

## cboldt

 *cowboy0629 wrote:*   

> Does anyone have a good set of rules that I can use.. or see.. I am really confused right now.. the rules I am using are the ones from Gentoo/Home Router and something happend last night when I went thru and changed the capital UDP and TCP to lower case.;. the hole network went down and I could not get it up and running again until I did a modem reboot and changed them back to capitals.. it also seems that these tables are very bad.. because allot of changes I try to make to them.. it locks my internal network off the network.. I am not sure where to start.. I had a friend try to fix them up for me and then I lost internet... I don't know what is going on...

 

I suspect you are making more changes than just the uppercase -> lowercase revision

In particular, if you followed my advice to get rid of the "iptables -I INPUT 1 -i ${LAN} -j ACCEPT" line, you closed off much of your network.  My mistake misreading subsequent rules as affecting packets headed for $LAN, when the subsequent rules were written to affect packets headed for "not $LAN."

Writing a firewall by hand is a relatively difficult programming activity.  If you don't  well understand what each of the program lines does, which means you also have to have a fairly good idea of how a firewall works, it is more likely the firewall won't do what you want.  I have a reasonably good handle on the principles, my hand coded firewall took about 50 attempts - using example code from shorewall, ipkungfu, multiple internet sources, etc. - and I believe it still contains errors that I don't intend.

I agree with the suggestion to use a higher level tool to write the firewwall rules, which you can then review using "iptables-save" or "iptables -L" or "iptables -nL".  There are a number of these higher level tools, and again I am at a loss to give my preference, because I don't have enough familiarity.  I have used ipkungfu, and stole some of the ideas in it for my hand-crafted firewall.

shorewall

ufw

ipkungfu

I persist with a hand crafted firewall because I have certain personality quirks (inertia, irrational bias to "lean," even "minimalist", and others) not because the hand crafted firewall necessarily works better.

You don't want to open your machine to any outsider, and give them root privileges.

----------

## alexcortes

I am not a expert but these are the rules I use, different case of yours anyway:

```
#!/bin/bash

IPT="/sbin/iptables"

IPTS="/sbin/iptables-save"

IPTR="/sbin/iptables-restore"

echo "Configuring IPv4 firewall..."

$IPT -F

$IPT -X

$IPT -Z

$IPT -N TCP

$IPT -N UDP

$IPT -P INPUT DROP

$IPT -P OUTPUT ACCEPT

$IPT -P FORWARD DROP

$IPT -A INPUT -i lo -j ACCEPT

$IPT -A INPUT -m conntrack --ctstate INVALID -j DROP

$IPT -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

$IPT -A INPUT -p icmp -m icmp --icmp-type 8 -m conntrack --ctstate NEW -j ACCEPT

$IPT -A INPUT -p udp -m conntrack --ctstate NEW -j UDP

$IPT -A INPUT -p tcp --tcp-flags FIN,SYN,RST,ACK SYN -m conntrack --ctstate NEW -j TCP

$IPT -A INPUT -p udp -j DROP

$IPT -A INPUT -p tcp -j REJECT --reject-with tcp-reset 

$IPT -A INPUT -j REJECT --reject-with icmp-proto-unreachable 

$IPT -A OUTPUT -p icmp -m conntrack --ctstate INVALID -j DROP

#SSH

$IPT -A TCP -s 192.168.0.0/24 -p tcp --dport 22000 -j ACCEPT

#Bittorrent

$IPT -A TCP -p tcp --dport 6880 -j ACCEPT

#KDEconnect

$IPT -A TCP -s 192.168.0.0/24 -p tcp --dport 1714:1764 -j ACCEPT

$IPT -A UDP -s 192.168.0.0/24 -p udp --dport 1714:1764 -j ACCEPT

#MPD Client

$IPT -A TCP -s 192.168.0.0/24 -p tcp --dport 6600 -j ACCEPT

echo "Done. ;-)"
```

----------

