Need to implement access control list with iptables

This may be simple ... or not.

I'd like to set up an iptables rule(s) to only permit connection by one or two specific IP addresses on eth0 and route valid connections to eth1. Assuming my public IP is 1.2.3.4, would that be something like:

iptables -A INPUT -i eth0 \! -s 1.2.3.4 -j DROP

and how about routing the traffic to eth1? Would that be:

iptables --table nat --append POSTROUTING --out-interface eth0 -j MASQUERADE

iptables --append FORWARD --in-interface eth1 -j ACCEPT

I'd like some advice before experimenting
LVL 1
MarkAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

gheistCommented:
Use VPN. IP and MAC can be spoofed at zero effort.
arnoldCommented:
You want to restrict your internal systems from accessing external resources/ports i.e. no facebook, peer to peer, etc.?

source address rule is not applicable as your system will not see connection from that IP unless an internal system loops out.

What is your setup
Eth0 is LAN side
Eth1 is your WAN side.

DNAT/SNAT depending which direction you are looking at.

IMHO, in your setup where the linux system functions as a router, your best bet is to use IP chains.
Incoming_traffic that is added to the input with -i <wan_interface>  as well as  to forward

the -s 192.168.x.x is the correct path.
MarkAuthor Commented:
geist:
Use VPN. IP and MAC can be spoofed at zero effort.
Yes, but I'm desiring slightly more than zero effort on my part. VPN is new territory for me and I want to either get something implemented with Linux ASAP, or I'm off to buy a $300 Sonicwall. Plus, I don't think VPN would be acceptable in this case. See my explanation of the configuration, below.

arnold:
You want to restrict your internal systems from accessing external resources/ports i.e. no facebook, peer to peer, etc.?
No, I want to restrict external system from internal access. What I actually have/want is:

Internet -- 1.2.3.4 --> [future firewall] ---> 1.2.3.4 [Samsung phone system]

Only voice mail is emailed from the Samsung which is currently connected directly to the Internet at 1.2.3.4. We've been DoS'd and need a firewall, but your typical off-the-shelf routers don't restrict incoming IPs (access lists). The IP(s) I want to let through belong to the phone service company. Nobody else needs to access the Samsung.

I'll try experimenting with:
iptables --table nat --append POSTROUTING --out-interface eth0 -j MASQUERADE
iptables --append FORWARD --in-interface eth1 -j ACCEPT

iptables -A INPUT -i eth0 \! -s 4.3.2.1 -j DROP

Open in new window

I'm hoping this will drop any source not equal to 4.3.2.1 (the Phone Company) and route all packets for all ports from 4.3.2.1 to eth1 (the Samsung with IP 1.2.3.4). I'm no iptables guru, so before pulling my hair out I thought one of you gurus could mentor me on this.
Discover the Answer to Productive IT

Discover app within WatchGuard's Wi-Fi Cloud helps you optimize W-Fi user experience with the most complete set of visibility, troubleshooting, and network health features. Quickly pinpointing network problems will lead to more happy users and most importantly, productive IT.

arnoldCommented:
You can define the port forwarding rule to include the source IP as
The rule you out unless other.

Iptables -t filter -I INPUT 4 -p tcp -m tcp -s 4.3.2.1 -dport 4020 --to-address 1.2.3.4:4020 -j Accept
Iptables -t filter -I FORWARD 4 -p tcp -m tcp -s 4.3.2.1 -dport 4020 --to-address 1.2.3.4:4020 -j Accept

Or something like that. Will setup access from 4.3.2.1 to your WAN_IP:4020 that will be forwarded through the firewall to 1.2.3.4:4020
Do you have a split IP allocation
I.e. Your provider gave you a block with a mask of 255.255.255.252 for the WAN side and then gave you another block of public IPs for the LAN side?

In your case you actually need to look at incorporating snort (iptables+snort) to build a Linux based router/firewall with deep inspection (IDS/IPS) snort will be the mechanism that would limit/minimize DOS, etc.
MarkAuthor Commented:
Will setup access from 4.3.2.1 to your WAN_IP:4020 that will be forwarded through the firewall to 1.2.3.4:4020
Not quite sure I get your example. Why are you forwarding to port 4040? And if it forwards to the same IP (1.2.3.4) won't that just send it right back to this same host in a loop?
Do you have a split IP allocation
No.

Maybe this is not as simple as I thought?
arnoldCommented:
That is what I am not clear with your example, are you configuring your linux box as a transparent firewall?
I thought your had a mistake between the WAN IP on one side and a LAN IP to which you want the packets to connect.

Lets try this way.
Your provider has a router that delivers to you a Public Connection, one or more public IPs?
Am I correct that you have a linux box that has two network cards one is getting the connection from the providers Router (WAN side) and the other is setup as a NAT for the LAN side.
On the WAN side you can handle one or more public IPs
And then using the rules bind the other public IPs as a subindex on the wan Side interface
ifconfig ethx primary_public_ip
ifconfig ethx:1 next_public_ip etc.
in iptables you will check whether the destination -d is primary or next and forward accordingly.

there is a http://www.fwbuilder.org/ that might be helpful. It is a GUI type of interface to construct/manage iptable rules

The reason I think chain are simpler is that you only need to add the chains
i.e.
incoming_rules
These will have the WAN to LAN rules
Outgoing_rules the LAN to WAN rules if any

Usually two entries must always be added one in the INPUT of the filter, the other in the prerouting of the nat

"Linux as a firewall"
There are several good writeups.


The reason I am suggestion the use of your own chains is that once you place your chains in the existing
i.e. for inbound traffic filter input and nat prerouting
Adding a complete entry into the incoming_only will setup all that is needed

The alternative is to accept all on the INPUT and let the prerouting/forward handle which traffic will be permitted and which will not.

The same applies on the outgoing side, filter output and NAT postrouting are the outgoing path

DNAT, SNAT and masquerade are needed DNAT for incoming traffic/port forwarding --to-destination
Snat to change the source of the packet usually you would need this on the outgoing side if you have multiple public IPs and would like for example to have mail leave using a different IP that the primary firewall IP.
i.e. www public_ip
mail next_public_ip
when email originates from your system you want the connection to appear as though it is coming from next_public_ip versus public_ip which is the default.
--to-source
MarkAuthor Commented:
Thanks for the detailed write-up. Lots of good information.
Am I correct that you have a linux box that has two network cards one is getting the connection from the providers Router (WAN side) and the other is setup as a NAT for the LAN side.
Not exactly. I'm not doing the usual firewall. I've done that aplenty. Here is my current setup:

Internet ---->1.2.3.4--->[Samsung Phone System]

That's it. A 3rd party Samsung Phone system is connected directly to the Internet at IP 1.2.3.4. No other IPs involved. No LAN, no subnet, no routers, only the ISP's cable modem.

The Samsung had a DoS attack a few days ago that made using the phones in the office impossible. The vendor suggested we need a firewall which will permit only their IP address incoming for maintenance/service. The Samsung needs outgoing to send VM emails. I can supposedly buy a horribly expensive appliance from Cisco or Sonicwall to do this, but I'm trying to create a Linux box to do the job instead. I want to end up with the diagram I posted originally:

Internet -- 1.2.3.4 --> [my Linux firewall] ---> 1.2.3.4 [Samsung phone system]

The firewall's job is to simply reject all Internet sources other than the phone vendor's which, for example, is 4.3.2.1. Anything at all from that source is to be passed to the Samsung. I'm supposing a connection from the Internet to eth0 on the "firewall" and a connection to the Samsung on eth1. I can't really change the IP on the Samsung to something else like a 192.168.0.0 address. It's programmed to 1.2.3.4, so I need to just filter everyone but 4.3.2.1 and pass the legit packets through to the Samsung.

That's the whole story.
arnoldCommented:
So you do want to setup a transparent firewall.

Here is a write up that will help

http://www.sjdjweis.com/linux/bridging/

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
MarkAuthor Commented:
arnold: excellent link! That got me most of the way there. Given the following setup:

Internet ---> [router 192.168.0.1] --->eth0 [br0 192.168.0.104] eth1 -----> eth0 [host 192.168.0.111]

Here is what I've got working:
    brctl addbr br0
    brctl addif br0 eth0
    brctl addif br0 eth1
    ifconfig br0 up
    ifconfig eth0 up
    ifconfig eth1 up

    ip addr add 192.168.0.104/24 brd + dev br0  # give IP address the the bridge for external access

    modprobe ip_conntrack
    modprobe ip_conntrack_ftp

    iptables -I FORWARD -m state --state INVALID -j DROP
    iptables -I FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT

    iptables -A FORWARD --in-interface eth1 --out-interface eth0 -j ACCEPT
    iptables -A FORWARD --in-interface eth0 --out-interface eth1 -p tcp -d 192.168.0.111 --destination-port ssh -j ACCEPT

   iptables -A FORWARD --in-interface eth0 --out-interface eth1 \! -d 192.168.0.111 -j REJECT

Open in new window


The script listed above lets me ssh from any computer on the LAN to 192.168.0.111. Great! Now to tune for my needs. First of all, I can really get to any port on 192.168.0.111, not just 22, for example, I can get the default "It Works!" webpage. I tried the following:
 
    iptables -P INPUT DROP
    iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
    iptables -A INPUT -i lo -j ACCEPT
    iptables -A INPUT -i eth0 -p tcp --dport 22 -j ACCEPT
    iptables -A INPUT -i eth1 -p tcp -j ACCEPT

    iptables -I FORWARD -m state --state INVALID -j DROP
    iptables -I FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT

    iptables -A FORWARD --in-interface eth1 --out-interface eth0 -j ACCEPT
    iptables -A FORWARD --in-interface eth0 --out-interface eth1 -p tcp -d 192.168.0.111 --destination-port ssh -j ACCEPT

Open in new window

Note that I removed the ! -d 192.168.0.111 because I figured the INPUT DROP policy would take care of that.

That didn't work. I can still ssh to ...111, but can also still access  port 80. And I've lost the ability to ssh to the firewall/bridge at ...104. two steps back!

Not sure how to fix this. I would have thought that the initial ACCEPT for port 22 on eth0 would accept all port 22 connections, and the FORWARD of port 22 for ...111 would forward requests specific to that IP (which it does), and any other port 22 requests would end up directed to the local host, but no.

Ideas how to fix that?
arnoldCommented:
Look at line 6 of your uploaded iptables rule.  You by default allow any traffic from eth1 which is the interface on which 192.168.0.111.

Your layout confuses me. Which interface is the incoming from the Internet?


Internet <=>eth0<->eth1<=>LAN
Or
Internet <=>eth1<->eth0<=>LAN
MarkAuthor Commented:
The Internet comes into the router 192.168.0.1 and that is connected to eth0 of the "firewall" (...104). The target Samsung "surrogate" (...111) is connected from its own eth0 to the firewall's eth1. Sorry, thought my diagram would be clearer on that.

I allow all input from 192.168.0.111 (Samsung) because it needs to send stuff out the the internet via the firewall box.
arnoldCommented:
Currently it looks as through the only traffic you allow into eth0 is when it is going to port 22.

When you say you can access port 80 from which side of the firewall!

Currently if you have a system behind eth1 and you access anything including going out and coming back over eth0

Also if you are using an IPmon the 192.168.0.x access to 192.168.0.111 is direct and does not go through the iptables rules.
gheistCommented:
You can limit access per IP in SSHD and in any webserver.
arnoldCommented:
i thought you wanted to restrict access to the Samsung based on the source, but your router already directs traffic via port forwarding while your transparent firewall dis missing the \! -s externalIP/range

I thought the Samsung had to have a Public IP.
MarkAuthor Commented:
arnold:
I thought the Samsung had to have a Public IP.
First of all, this is a testing configuration. I'm trying to figure out these firewall rules on a couple of linux systems I've cobbled together. If I get this working it should be no big deal to use the real IPs. For this test, we'll "pretend" that the Samsung public IP is 192.168.0.111.
Currently it looks as through the only traffic you allow into eth0 is when it is going to port 22.
That's what I want, but it's not working that way. So, from some other host:
1 19:51:23 mfoley@192.168.0.146:~
>lynx --dump 192.168.0.111
                                   It works!

Open in new window

I don't think that request should be let through.
Currently if you have a system behind eth1 and you access anything including going out and coming back over eth0

Also if you are using an IPmon the 192.168.0.x access to 192.168.0.111 is direct and does not go through the iptables rules.
You'll have to elaborate a bit. Don't know what you mean. This setup is exactly as described in your link http://www.sjdjweis.com/linux/bridging/. Maybe browse through that, it's short. He likely explains it much better than I am. Don't know what IPmon is.

geist:
You can limit access per IP in SSHD and in any webserver.
The final step in this exercise is to limit by source, not just for ssh, but for any port destined for the 192.168.0.111 IP. For right now, just trying to restrict the ports. Trying to keep the variables to a minimum.


arnold:
i thought you wanted to restrict access to the Samsung based on the source, but your router already directs traffic via port forwarding while your transparent firewall dis missing the \! -s externalIP/range
Another fellow, wildwizard, responding in http://www.linuxquestions.org/questions/linux-networking-3/iptables-to-implement-access-control-list-4175544959/, suggested that \! -s was a "bad idea" and recommended setting the policy to drop/reject.

BUT not sure any of that makes a difference in

a) why are http requests getting through?

b) why does the listed conf now prevent me from accessing the firewall at 192.168.0.104? Note that in my first listing in post ID: 40828845 I can ssh 192.168.0.104 and in the 2nd listing I can't.
arnoldCommented:
The issue is with the source of your request.


You have a LAN using 192.168.2.0/24 and this is the internet.
Your router's wan IP is on the 192.168.2.4 as an example
With the LAN side being 192.168.0.0/24
Then make attempts from the  192.168.2.x but in this example, your router will be configured with port forward

Try this.

Connect the test device with IP 192.168.0.111 to the eth1 of your transparent firewall with eth0 remaining as is and any system you will be testing from into the router's LAN.
See if that works as intended. I.e. The transparent firewall will only protect the test 192.168.0.111 system.

Explicitly add a deny rule.
on input for -i eth0 after the ssh rule
MarkAuthor Commented:
arnold:
Connect the test device with IP 192.168.0.111 to the eth1 of your transparent firewall with eth0 remaining as is
That is exactly how I have it. The ...111 device is not connected to the router directly. Sorry if I was unable to make that clear. I do have lots of other devices on the LAN and they are not affected by all this.
Explicitly add a deny rule. on input for -i eth0 after the ssh rule
What should the deny rule look like? I've changed it back to the original semi-working script and added what I think is a deny rule at line 6, below:
    iptables -I FORWARD -m state --state INVALID -j DROP
    iptables -I FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT

    iptables -A FORWARD --in-interface eth1 --out-interface eth0 -j ACCEPT
    iptables -A FORWARD --in-interface eth0 -s 192.168.0.146 --out-interface eth1 -p tcp -d 192.168.0.111 --destination-port ssh -j ACCEPT
    iptables -A FORWARD --in-interface eth0 --out-interface eth1 -p tcp -d 192.168.0.111 -j REJECT

    iptables -A FORWARD --in-interface eth0 --out-interface eth1 \! -d 192.168.0.111 -j REJECT

Open in new window

Doesn't work. Can still get through to http. Note that I also added "-s 192.168.0.146" to line 5. Makes no difference. Any host can get to 192.168.0.111. Apparently, I am not able to either restrict connections from a particular IP or restrict to a particular port. Obviously I'm doing it wrong. Seems like this one thing should be simple. Does it have to be an INPUT rule?
arnoldCommented:
Can you post the iptables -L --line-numbers

The example in the bridging writeup.
Not sure whether the placement of an ip on eth0 alters/interferes with the bridging transparent firewall.

Where is port 80 running.  You are adding references and what is or is not working without previously providing a context
MarkAuthor Commented:
The example in the bridging writeup.
Not sure whether the placement of an ip on eth0 alters/interferes with the bridging transparent firewall.
Hmmm, well Mr. Weis wrote, "If you really, really think you need to have an IP address on the firewall, you can give one to the interface br0. DO NOT give an IP to eth0 or eth1, bad things will happen. I'm not sure what, but the bridging docs told me so", so I assume it's OK. I did put the IP on br0.
Where is port 80 running.  You are adding references and what is or is not working without previously providing a context
The ports I am testing are on the target test machine on the other side of the firewall. The test machine is 192.168.0.111. I've made more changes since the last posting but still no joy. Simply, I want to be able to restrict access to the host at 192.168.0.111 by both IP and port. So far nothing is working. Any host can still get to this test system and on any port (e.g. 22, 80). Unless I can apply some restrictions to this setup, then the whole exercise is fairly uselss. Anyone can get to anything without a firewall!

Below is the latest, with the iptables --line-numbers below that. In the following, I thought I'd try DROPing all INPUT by default (line 1), then permitting input only from IP 192.168.0.146 destined for 192.168.0.111 only to port 22 (line 4). I'm allowing anything to connect to the firewall at 192.168.0.104 (line 5). I'm forwarding only port 22 requests destined for 192.168.111 to eth1 (line 12) and rejecting everything else going to 192.168.0.111 (line 13). As I said, none of this works as intended.
   iptables -P INPUT DROP
    iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
    iptables -A INPUT -i lo -j ACCEPT
    iptables -A INPUT -i eth0 -s 192.168.0.146 -p tcp -d 192.168.0.111 --dport 22 -j ACCEPT
    iptables -A INPUT -i eth0 -d 192.168.0.104 -j ACCEPT
    iptables -A INPUT -i eth1 -p tcp -j ACCEPT

    iptables -I FORWARD -m state --state INVALID -j DROP
    iptables -I FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT

    iptables -A FORWARD --in-interface eth1 --out-interface eth0 -j ACCEPT
    iptables -A FORWARD --in-interface eth0 --out-interface eth1 -p tcp -d 192.168.0.111 --destination-port ss$
    iptables -A FORWARD --in-interface eth0 --out-interface eth1 -p tcp -d 192.168.0.111 -j REJECT

Open in new window

1 00:16:06 root@firewall:~
>iptables -L -v -n --line-numbers
Chain INPUT (policy DROP 623 packets, 64974 bytes)
num   pkts bytes target     prot opt in     out     source               destination
1      516 41760 ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0           state RELATED,ESTABLISHED
2       12  1152 ACCEPT     all  --  lo     *       0.0.0.0/0            0.0.0.0/0
3        0     0 ACCEPT     tcp  --  eth0   *       192.168.0.146        192.168.0.111       tcp dpt:22
4        0     0 ACCEPT     all  --  eth0   *       0.0.0.0/0            192.168.0.104
5        0     0 ACCEPT     tcp  --  eth1   *       0.0.0.0/0            0.0.0.0/0

Chain FORWARD (policy ACCEPT 498 packets, 50438 bytes)
num   pkts bytes target     prot opt in     out     source               destination
1       63  8154 ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0           state RELATED,ESTABLISHED
2        0     0 DROP       all  --  *      *       0.0.0.0/0            0.0.0.0/0           state INVALID
3        0     0 ACCEPT     all  --  eth1   eth0    0.0.0.0/0            0.0.0.0/0
4        0     0 ACCEPT     tcp  --  eth0   eth1    0.0.0.0/0            192.168.0.111       tcp dpt:22
5        0     0 REJECT     tcp  --  eth0   eth1    0.0.0.0/0            192.168.0.111       reject-with icmp-port-unreachable
6        0     0 REJECT     all  --  eth0   eth1    0.0.0.0/0           !192.168.0.111       reject-with icmp-port-unreachable

Chain OUTPUT (policy ACCEPT 539 packets, 67110 bytes)
num   pkts bytes target     prot opt in     out     source               destination

Open in new window

MarkAuthor Commented:
Here's an interesting thing. When I remove ALL the firewall rules. I can still get to the test host at 192.168.0.111 (no, I can't get there if the bridge/firewall is not up). So, despite all the FORWARD rules listed in Mr. Weis' link, everything forwards to eth1 with only the brctl settings! Apparently, the iptables settings are completely ignored. No wonder I can't do any restricting. Perhaps this link wasn't the right trail after all.

This is my first shot using bridge settings. I know nothing.
arnoldCommented:
I think the related reference is in play as all your tests are from the same underlying network, 192.168.0.x/24 which related matches.  Remove the related in the input/forward reference and see if that cures your issue. Note the example desks with securing the LAN from the Internet meaning the incoming traffic will not be related to the systems shielded by the transparent firewall.
MarkAuthor Commented:
Nope, removing RELATED made no difference at all.

Keep in mind that the test machine (192.168.0.111) is not connected to the LAN at all. It is connected to the firewall's (192.168.0.104) eth1. If the firewall is not up, 192.168.0.111 has no connection to or from anything.

Given that I can connect to 192.168.0.111 from any workstation in the LAN without any iptables rules at all. I have to conclude that routing due to the bridging occurs before the iptables rules are processed. It seem that packets are sent immediately to eth1 before any checking. If that's the case, I can't use the bridging idea.
arnoldCommented:
Mark,

You gave eth0 the IP, you need to give br0 the IP you want to access the transparent firewall on.

Rereviewed the write up in the build a transparent firewall to make sure I did not miss something.  It has a clear warning on not assigning an IP to either eth0 nor eth1.
MarkAuthor Commented:
OK, I've determined by talking with the Samsung tech that what I want to do is not really possible with a bridge setup, nor can the Samsung keep the same IP as the firewall. The Samsung has to be on a LAN subnet. Therefore, I can accomplish this with more straighforward iptables rules.

Consequently, I'm going to close this question. I've almost got what I want. I can redirect to the desired ports on the Samsung with access restricted to a specific external IP. However, I want to be able to access the firewall itself, but having trouble doing that unless I am connecting from the same restricted IP, even though I don't think I've restricted access to the firewall host by IP. I've opened a new question: http://www.experts-exchange.com/questions/28689726/iptables-need-to-permit-hosts.html, so we'll forget about this mess and start clean. Check that one out.
MarkAuthor Commented:
This question is a dead-end, but arnold's link was very useful for bridge configuration
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Linux Networking

From novice to tech pro — start learning today.