Internet filetering/security

Discussion in 'Tomato Firmware' started by cobrax2, May 31, 2018.

  1. cobrax2

    cobrax2 Serious Server Member

    Hi guys
    I manage a small enterprise's network. I'm not an expert, but i have some knowledge :)
    The whole network gets on the internet through a asus router with tomato on it. There are about 20 computers, on the same lan, connected to a big switch and then one port goes into the router. Now the problem: recently it became a necessity to cut off from the internet some of the computers completely. All of the computers must communicate with each other in the lan, but some must not get internet. Now, i can filter in the tomato firewall to only accept outside communications to some of the mac's and that would be the easy way. Bu what one guy with some knowledge sniffs the mac of one of the allowed computers and changes his own to that and goes through? Is there another, safer way?
    Thank you!
     
  2. Mercjoe

    Mercjoe Network Guru Member

    Look at access restrictions. You can use an IP address or a MAC address to block all internet access.

    The computers will still be on the LAN communicate with each other nicely.

    And yes, it works here at my house nicely. I use it to block the kids computers and tablets on school nights.
     
  3. jerrm

    jerrm Network Guru Member

    You sound like your on the right track. Use access restriction and only ALLOW specific macs.

    If someone is savvy enough to clone a mac (and overcome the conflicts) without being detected, then you have an issue. Odds of that are relatively slim. If someone attempted to do so it should be a fireable offense.

    If it's a business owned PC, hopefully he won't have rights to change the mac.

    If you can move the "blocked" PCs onto their own vlan it would make mac spoofing more difficult, and could still be set up to see LAN<->VLAN.

    Only real way to lock it down on a single lan is something like an 802.1x aware smart switch or maybe an authenticated proxy (assuming no one shares passwords).
     
    Monk E. Boy and Mercjoe like this.
  4. cobrax2

    cobrax2 Serious Server Member

    well the problem is that i have to give them admin accounts as some applications don't work without. so then they can change their mac
    if i move the blocked pcs onto another vlan, and that vlan will communicate with the other, normal one, can't then he still sniff the mac of a normal pc?
    can i install a web proxy on tomato easily enough? that is the only way i can think of to use passwords for all.
     
  5. cobrax2

    cobrax2 Serious Server Member

    also, if i block from access restriction, is there a way to only ALLOW for some mac's? i only find a way to block. i would like to block all, and allow only specific macs. i think it's better than blocking some macs
     
  6. maurer

    maurer Network Guru Member

    looks like you need something better than tomato - it just wasn't built with all those security features in mind.
    the cheapest would be to get an old PC and install OPNsense on it (pfSense fork - working on legacy hw)
    there you should be able to install a web proxy that would run decently for more than 1 user (as tomato on asus would) and the only downside would be the power consumption - maybe a reason to get the manager to invest in some more up to date mini pc with low consumption :)
     
  7. cobrax2

    cobrax2 Serious Server Member

    ok, thanks. for now the mac filtering should do, if nothing else is possible
     
  8. Monk E. Boy

    Monk E. Boy Network Guru Member

    FWIW, MACs are unique values per network segment. He can't change the system's MAC to the MAC of another system without breaking his system and the system he cloned from. The instant two systems with the same MAC appear on the same network segment both systems will have their network broken. They're far more likely to change their IP address though, not all network cards allow you to change the MAC addresses. There's also the fact that he would only see MAC addresses for traffic directed at his system or performing network broadcasts, he can't sniff "all" traffic just by plugging into a switch port. He can only sniff traffic directed at his system. The only way to sniff all traffic is to actually break into the switch and start cloning ports there.
     
    Last edited: Jun 4, 2018
  9. cobrax2

    cobrax2 Serious Server Member

    thanks
    i've done it this way.
    one question: is there a way for iptables to allow the forward chain from the wireless interface to the internet? i mean, the wireless clients get bridged in the same vlan as the lan. so when i closed the internet for all lan, i've closed it for the wireless clients too.
    what i've done until now is something like this:
    iptables -I FORWARD -o wan -j DROP (wan is a generic name, i dont remember exactly what its called)
    and then added accept commands for each mac that i wanted to go out on the internet
    now how can i specify that ALL wireless clients should be allowed?
    if i use iptables -I FORWARD -o wan -i eth0 -j ACCEPT (eth0 being what the wirelles interface is called) it doesnt work...
    thanks
     
  10. Monk E. Boy

    Monk E. Boy Network Guru Member

    Using -I means inject the rule to the top of the list. So when using -I you have to add rules in reverse order. The first one you add becomes 1, the second one you add becomes 1 and the first one becomes 2, and so on. So if you have a drop rule you want to add that first then add the allow rules after it, so the rules end up in the reverse order of what you add. Ideally you should use -A and add them to the existing rulebase where they make sense within the context of the existing rules but for testing purposes I always use -I while figuring out how to make them work first.

    To my knowledge WLAN and LAN are bridged to a single vlan interface. That may be the issue, though I would expect it to affect both interfaces equally.
     
  11. cobrax2

    cobrax2 Serious Server Member

    the filtering is ok, i've inserted the rules correctly, first drop and then accept.
    the problem is how to differentiate between wlan and lan?
    thanks
     
  12. koitsu

    koitsu Network Guru Member

    Warning: long post, because what is being discussed already appears to contain an approach that is on the way to Extreme Pain and Potential Job Loss. I expect you to read this, not skim it. :) You will find an answer to a couple things that might get your hopes up, and some disappointing news otherwise.

    1. Make sure your ACCEPT rules come first, followed by DROP or REJECT. When a packet arrives, it gets analysed in the order (rule-wise) of "top to bottom", hence your ACCEPT must come before your DROP/REJECT. Use the flag --line-numbers to see the ordering. I recommend getting in the habit of using flags -v -n --line-numbers as a general default. I still maintain Linux is stupid for not making this the default.

    2. This thread doesn't list the exact model of router you have, so I can't tell you definitively what interface to match against (for wired LAN vs. wireless). The general interfaces are these, but again, it varies per model -- and if you have custom VLANs involved, the situation may vary even more. These interface names are what correlate with the kernel interface naming convention, and are not "names" or "descriptions"; they are what show up in /sbin/ifconfig and are what iptables will key off of:

    eth0 = All 5 Ethernet ports (i.e. LAN ports and WAN port). No IP address bound; generally do not use this
    eth1 = 2.4GHz wireless (WLAN). No IP address bound; generally do not use this
    eth2 = 5GHz wireless (WLAN). No IP address bound; generally do not use this
    vlan1 = LAN (4-port Ethernet). No IP address bound; generally do not use this
    vlan2 = WAN (1-port Ethernet). This has your WAN IP bound to it
    br0 = Software bridge of eth1, eth2, and vlan1. This has your router's LAN IP (ex. 192.168.1.1) bound to it. This is effectively "your LAN as a whole".

    You can use iptables' -i (inbound) and -o (outbound) flags to match against a specific interface.

    However, matching against vlan1 for wired LAN traffic will not work -- the packet will not match. Same goes for eth0 (do not ever use this), eth1, and eth2. This has to do with "where" iptables sits in the traffic flow for forwarded traffic: such traffic is always going to match against interface br0. Sorry, that's just how it works. Proof using something like iptables -A wanout -d 8.8.8.8 -j LOG and sending a packet to 8.8.8.8 and then looking at what the IN interface is (won't matter if it's a WiFi client or a wired client):

    Code:
    IN=br0 OUT=vlan2 SRC=xxx.xxx.x.xx DST=8.8.8.8 LEN=84 TOS=0x00 PREC=0x00 TTL=63 ID=31615 PROTO=ICMP TYPE=8 CODE=0 ID=20160 SEQ=0
    
    It may be possible to use ebtables for this particular task, however my experience with ebtables on TomatoUSB has always resulted in a kernel panic (router crash/reboot), so I do not recommend experimenting with it. You have been warned.

    Skimming DD-WRT's forum shows that apparently they got all of this working somehow, so if it's an important feature, you may want to consider a different firmware. Or, since this is a commercial company, I'd suggest considering something like MikroTek hardware where it's designed for exactly this kind of thing (and you get commercial support for it). Otherwise you will need to "work around it".

    3. When injecting/adding rules to an existing Tomato-managed rule set, you need to be extremely careful WHERE in the relevant chain you inject them. Doing it wrong could result in blocked packets which should not be blocked, or worse, permitted packets that should not be permitted. This situation is made more complicated by things like state tracking, which Tomato (like most Linux firewalls, and certainly NAT) uses. Furthermore, injection of rules at the "wrong place" can sometimes result in excess CPU, depending on what all is being injected. I'll cover part of this in a moment.

    What you've done in post #9 indicates you have added to the very top of the firewall a rule that DROPs literally any packet destined on the outbound interface of wan (presumably this is vlan2, though more appropriately when scripted, it should probably be $(nvram get wan_iface). So your FORWARD chain probably looks something like this (precision matters, so I am having to make assumptions):

    Code:
    root@gw:/tmp/home/root# iptables -L FORWARD -n -v --line-numbers
    Chain FORWARD (policy DROP 0 packets, 0 bytes)
    num   pkts bytes target     prot opt in     out     source               destination
    1        0     0 DROP       all  --  *      vlan2   0.0.0.0/0            0.0.0.0/0
    2        0     0 ACCEPT     all  --  br0    br0     0.0.0.0/0            0.0.0.0/0
    3    16470  830K DROP       all  --  *      *       0.0.0.0/0            0.0.0.0/0            state INVALID
    4     111M  105G ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            state RELATED,ESTABLISHED
    5     1258  125K wanin      all  --  vlan2  *       0.0.0.0/0            0.0.0.0/0
    6     218K   42M wanout     all  --  *      vlan2   0.0.0.0/0            0.0.0.0/0
    7     218K   42M ACCEPT     all  --  br0    *       0.0.0.0/0            0.0.0.0/0
    8     1241  124K upnp       all  --  vlan2  *       0.0.0.0/0            0.0.0.0/0
    
    The problem with this approach should become apparent given the Tomato-managed (and very important) state analysis rules that are now preceded by an explicit DROP -- and worse, by your desire, that which will be preceded by an ACCEPT. I can already tell that what you're wanting is to do something like this:

    Code:
    Chain FORWARD (policy DROP 0 packets, 0 bytes)
    num   pkts bytes target     prot opt in     out     source               destination
    1        0     0 ACCEPT     all  --  *      vlan2   0.0.0.0/0            0.0.0.0/0            MAC 11:22:33:44:55:66
    2        0     0 DROP       all  --  *      vlan2   0.0.0.0/0            0.0.0.0/0
    3        0     0 ACCEPT     all  --  br0    br0     0.0.0.0/0            0.0.0.0/0
    4    16484  831K DROP       all  --  *      *       0.0.0.0/0            0.0.0.0/0            state INVALID
    5     111M  105G ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            state RELATED,ESTABLISHED
    6     1258  125K wanin      all  --  vlan2  *       0.0.0.0/0            0.0.0.0/0
    7     218K   42M wanout     all  --  *      vlan2   0.0.0.0/0            0.0.0.0/0
    8     218K   42M ACCEPT     all  --  br0    *       0.0.0.0/0            0.0.0.0/0
    9     1241  124K upnp       all  --  vlan2  *       0.0.0.0/0            0.0.0.0/0
    
    This added ACCEPT in front of that DROP opens you up to security problems relating to spoofed packets, especially on existing outbound NAT'd connections. You no longer have the benefits of state table analysis or security of the subsequent rules. This is bad, and could cost you your job if someone was to be extremely careful with IP address spoofing (remember: while TCP is stateful, UDP and ICMP are not, but all of them are tracked in conntrack!). If you don't understand why this is a security problem, then I suggest taking some actual network classes or training courses on understanding IP networking, specifically on how firewall security and how NAT works (particularly WRT state-tracking firewalls). You owe it to your employer to know what you're doing.

    So how do you do this properly?

    You should be using are the existing Tomato chain called wanout and not playing with FORWARD. Why? Because the FORWARD chain rules that use the wanout chain come after the related state table analysis chains (rules #2 and #3 in the immediate below paragraph), and already matches against the outbound WAN interface for you. I will demonstrate how this works, and to understand two nuances relating to it. Let's start with this, which looks like a nearly-stock TomatoUSB firewall set for FORWARD and wanout:

    Code:
    root@gw:/tmp/home/root# iptables -L -n -v --line-numbers
    ...
    Chain FORWARD (policy DROP 0 packets, 0 bytes)
    num   pkts bytes target     prot opt in     out     source               destination
    1        0     0 ACCEPT     all  --  br0    br0     0.0.0.0/0            0.0.0.0/0
    2    16487  831K DROP       all  --  *      *       0.0.0.0/0            0.0.0.0/0            state INVALID
    3     111M  105G ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            state RELATED,ESTABLISHED
    4     1258  125K wanin      all  --  vlan2  *       0.0.0.0/0            0.0.0.0/0
    5     218K   42M wanout     all  --  *      vlan2   0.0.0.0/0            0.0.0.0/0
    6     218K   42M ACCEPT     all  --  br0    *       0.0.0.0/0            0.0.0.0/0
    7     1241  124K upnp       all  --  vlan2  *       0.0.0.0/0            0.0.0.0/0
    
    ...
    
    Chain wanout (1 references)
    num   pkts bytes target     prot opt in     out     source               destination
    
    Let's add a block for all outbound forwarded traffic, with some exceptions (based on client MAC), to wanout:

    Code:
    root@gw:/tmp/home/root# iptables -A wanout -m mac --mac-source 11:22:33:44:55:66 -j ACCEPT
    root@gw:/tmp/home/root# iptables -A wanout -j DROP
    
    Note what flags I used (-A), and what order I ran the commands. Now let's look at the wanout chain again:

    Code:
    root@gw:/tmp/home/root# iptables -L wanout -n -v --line-numbers
    Chain wanout (1 references)
    num   pkts bytes target     prot opt in     out     source               destination
    1        0     0 ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            MAC 11:22:33:44:55:66
    2        0     0 DROP       all  --  *      *       0.0.0.0/0            0.0.0.0/0
    
    Now let's test it. First, let's send 3 ICMP echo packets to 8.8.8.8 (a Google DNS server that responds to ICMP echo), from the system that is MAC 11:22:33:44:55:66:

    Code:
    $ ping -c 3 8.8.8.8
    PING 8.8.8.8 (8.8.8.8): 56 data bytes
    64 bytes from 8.8.8.8: icmp_seq=0 ttl=59 time=8.950 ms
    64 bytes from 8.8.8.8: icmp_seq=1 ttl=59 time=7.828 ms
    64 bytes from 8.8.8.8: icmp_seq=2 ttl=59 time=8.141 ms
    ^C
    --- 8.8.8.8 ping statistics ---
    3 packets transmitted, 3 packets received, 0.0% packet loss
    round-trip min/avg/max/stddev = 7.828/8.306/8.950/0.473 ms
    
    Now let's check the firewall rule counters:

    Code:
    Chain wanout (1 references)
    num   pkts bytes target     prot opt in     out     source               destination
    1        1    84 ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            MAC 11:22:33:44:55:66
    2        0     0 DROP       all  --  *      *       0.0.0.0/0            0.0.0.0/0
    
    And what about other clients which aren't MAC 11:22:33:44:55:66? Let's try it from one... nope, no response. The packets are blocked. I sent two, just as a test, from a Windows 7 box (payload is smaller than on 11:22:33:44:55:66 which in my case is a FreeBSD machine):

    Code:
    Chain wanout (1 references)
    num   pkts bytes target     prot opt in     out     source               destination
    1        1    84 ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            MAC 11:22:33:44:55:66
    2        2   120 DROP       all  --  *      *       0.0.0.0/0            0.0.0.0/0
    
    Now for the nuances:

    1st question you should have: why does the packet counter for the ACCEPT rule only have 1 packet, when it should have 3 packets, as you sent 3 ICMP echos?

    Answer: Linux NAT state table, specifically conntrack, takes care of permitting the subsequent/related packets. The first packet, since it was permitted, acts as a "trigger point" for conntrack to keep track of the flow. This is good and (in most cases) what you want. The subsequent 2 packets were therefore handled by rule 3 in the FORWARD chain. We can even verify that's the case by looking at the conntrack table:

    Code:
    root@gw:/tmp/home/root# grep 8.8.8.8 /proc/net/ip_conntrack
    icmp     1 28 src=XXX.XXX.X.XX dst=8.8.8.8 type=8 code=0 id=5821 src=8.8.8.8 dst=XX.XXX.XX.XX type=0 code=0 id=5821 mark=0 use=2
    
    The first src in this case would be the LAN IP of the system matching MAC 11:22:33:44:55:66, and 2nd dst would be the WAN IP of the router. That's all correct/normal.

    2nd question you should have (if paying super close attention, but if not, it's easy to overlook): what if you've added an ACCEPT for something, which then has entries in conntrack/state table, but then later you remove that ACCEPT (delete the ACCEPT rule with iptables)? I.e. you have a client which is permitted access, but later needs to be rescinded? Are there concerns?

    Answer: yes, for existing flows which are already in conntrack and active, these flows will continue to work/function despite removal of the ACCEPT rule. This is a known "complication" with state tables. The network administrator needs to be aware of this when removing the rule, and check the conntrack table for any entries matching the now-removed LAN IP of the client, and if there are some, do one of the following:

    a) Add a temporary DROP or REJECT for the client in question, into the FORWARD chain (not wanout! I just covered why earlier!), specifically a rule that's *before* the "state RELATED,ESTABLISHED" rule. You can let this DROP/REJECT sit for some time (I would recommend 30 minutes, but just watch /proc/net/ip_conntrack to make sure), then can delete the rule once you've verified all the conntrack entries are gone/expired.

    b) Clear the conntrack table by doing echo f > /proc/net/nf_conntrack or conntrack -F. However, see below.

    (b) runs the risk that existing NAT flows will suddenly break (connections will sever) and IP or TCP stacks on clients may show errors. But Linux is fairly good about figuring out what was previously a working/valid network flow and "re-establishing" that entry in the state table so that interruptions are virtually nil (as long as the client has some form of TCP retry, which is common). I tend to opt for (b) whenever possible.

    On TomatoUSB, however, you cannot clear the conntrack table using the echo f methodology -- you will receive an I/O error -- and there is no conntrack utility (it's part of conntrack-tools and not included). In short: (b) is not really an option on stock TomatoUSB.

    Remember: this applies to EXISTING/ACTIVE flows; any new sockets/flows/etc. will be dropped (as they should be), it's only existing flows which will continue to work until expiry. Ever wonder what (most of) those values in Advanced -> Conntrack/Netfilter were for? Now you know.

    Good luck, HTH.
     
  13. cobrax2

    cobrax2 Serious Server Member

    thank you very much for the very detailed explanation. i've moved my rules to wanout interface, if you said that it's better this way. i think i already tried it before, but didnt work. maybe i did something wrong then, now it works fine :)
    as for separating the wireless clients, there is no way to do this? maybe some dhcp options to give them a specific range and then mark that as "safe"? can it be done?
    thank you again!
     
  14. Sean B.

    Sean B. LI Guru Member

    Put the wireless interfaces into their own VLAN/subnet ( I'd suggest this for all the differing groups honestly ). For example: Bridge = br2 - 192.168.3.0/24 - VLAN3 - bridge eth1 and eth2 to br2. You can then deny that bridge any access to the WAN, allow it access to the "not blocked" LAN, or allow it access to specific devices on the "not blocked" LAN only, etc.
     
  15. cobrax2

    cobrax2 Serious Server Member

    hmm this is a bit beyond my capabilities, i can only bridge eth1 to br0 or wan. the rest are greyed out
    and how can i make this vlan communicate with the rest of the lan? i think i need to push some route to them, right?
     
    Last edited: Jun 5, 2018
  16. cobrax2

    cobrax2 Serious Server Member

    lol managed to get locked out of the router, had to reset. this bridging thing is dangerous stuff :)
     
  17. Sean B.

    Sean B. LI Guru Member

    You first need to create the bridge/subnet under Basic->Network.
     
  18. jerrm

    jerrm Network Guru Member

    For the most part no, but even if the macs leak, it doesn't matter as you can block the entire subnet from having internet access with a single rule.

    You can allow vlanA to vlanB, .and allow vlanA to WAN, and block vlanB to WAN. Even if they try to spoof a mac they are still in vlanB and vlanB remains blocked. Wired devices would have to plug into a vlanA connected port to circumvent. If it's cubicles - it's easy enough to bypass using a $10 switch plugged into the neighboring vlanA cube to share the connection. Wireless devices would have to know the vlanA key.

    Nothing is going to be 100%, but if you layer approaches it becomes more trouble than it's worth to most people.
    .
    Several proxies including Squid in Entware. Performance is not great running on router hardware.
     
  19. cobrax2

    cobrax2 Serious Server Member

    yes, managed to do that, also to bridge as you said, but then the wireless network just dissapeared for the wireless clients :( just couldn't be "seen"
    then i played some more with the bridges and got locked out of the router. oh well, restored config, all back to normal now, just don't know what else to do next
    thanks again guys!
     
  20. maurer

    maurer Network Guru Member

    mac-ip allow rules should be enough for tomato.
    more security means more $
     
  21. Monk E. Boy

    Monk E. Boy Network Guru Member

    That's my general approach to controlling troublemakers. I put a security framework in place. When they bypass it, I figure out how they bypassed it, then create additional security to block the bypass. A couple years of this and the layers build up to the point that troublemakers get frustrated but can't actually do any damage. It's kind of cat and mouse but in my case the mice are only around for a year or two and then a new batch of mice come in and start over at square one, but with no knowledge of what the previous mice did.

    I do this with full approval of management, meaning if anyone is actually destructive they won't even be around for a year. Without the stick to back you up you'll find it very frustrating to implement security. If someone gets caught bypassing security they get the stick.
     
  22. cobrax2

    cobrax2 Serious Server Member

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice