[olug] How can I sever IPtables established connections for only certain IPs?

Ben Hollingsworth obiwan at jedi.com
Tue May 23 13:35:20 CDT 2023


Heh.  My current IPtables config is over 700 lines, so I think 
converting to a different platform will be a bit more complex than 
that.  Thanks for the pointers, though.  I'll definitely save them for 
future reference.

On 5/23/23 13:15, Lou Duchez wrote:
> Perhaps now's the time to take the plunge with nftables. The sample I 
> provided is a working sample - I actually ran it on my router to make 
> sure it works - and other than tweaking IP addresses to your purposes, 
> it should be ready to go. I think you'd just drop a couple lines like 
> this in my_filter_forward:
>
> ip saddr 192.168.1.240 drop
> ip daddr 192.168.1.240 drop
>
> ... I am noting that there's not even a "conntrack" line in there 
> because it forwards everything by default, so there's no need to even 
> check "conntrack". If the default were "drop", that's when the 
> "conntrack" line would be necessary.
>
>
> On 5/23/2023 1:57 PM, Ben Hollingsworth wrote:
>> That's a great writeup.
>>
>> I've been very fond of the fwbuilder GUI for running IPtables. I 
>> haven't typed a raw command in years.  The down side is that it has 
>> no facility for doing what you suggested (moving rules above 
>> conntrack), so I'll finally have to get my hands dirty again. That 
>> shouldn't be too hard, I guess.
>>
>> On 5/23/23 12:39, Lou Duchez wrote:
>>> While I'm in a mood to be expansive, I remember what a hassle it was 
>>> for me to learn nftables. Here is the writeup that I would have 
>>> loved to have had back in the day, because I think this makes things 
>>> simple.
>>>
>>> NFTABLES CONCEPTS
>>>
>>> nftables operates via nested sections contained between curly brackets.
>>>
>>> The highest level section is the "table", and when you define your 
>>> table, you need to specify the "family" it is to govern ("ip" for 
>>> IPv4, "ipv6" for IPv6, "inet" for both, etc), plus a name. You can 
>>> have more than one table for a given family, for your own 
>>> organizational purposes.
>>>
>>> To do NAT and masquerading, you have to use "ip" or "ipv6", but not 
>>> "inet". So with that in mind, we will do a family of "ip", and our 
>>> table will start with:
>>>
>>> table ip myiptable {
>>>
>>> Within a table you can create "chains", which are sets of rules. 
>>> Additionally you can hook them to specific events; for example, the 
>>> first line in a chain might read:
>>>
>>> type filter hook input priority 0; policy accept;
>>>
>>> And that tells you that this chain is to be traversed during the 
>>> "filter" phase of inbound traffic. Also, this chain's priority is 
>>> "0" (which means it executes before a comparable chain with priority 
>>> of "1"), and any traffic that is not otherwise disposed of in this 
>>> chain leaves the chain with a status of "accept".
>>>
>>> Here is a chain that allows only loopback traffic and ports 80 and 
>>> 443, and drops everything else:
>>>
>>> chain myinput {
>>>
>>> type filter hook input priority 0; policy drop;
>>>
>>> ct state established,related accept
>>>
>>> iifname "lo" accept
>>>
>>> tcp dport 80 accept
>>>
>>> tcp dport 443 accept
>>>
>>> }
>>>
>>> Chains can call other chains by name; that's why you'd create a 
>>> chain that doesn't have any hook instructions, so it can be treated 
>>> like a subroutine that you can "jump" to.
>>>
>>> You can also create sets of IPs, so for example you could create a 
>>> set of trusted IPs, and then test against it something like: "ip 
>>> saddr @trusted_ips accept".
>>>
>>> So, how do we put this together? A very simple router 
>>> /etc/sysconfig/nftables.conf would look like:
>>>
>>>
>>> table ip myiptable {
>>>
>>>    # traffic with a destination of this server
>>>
>>>   chain my_filter_input {
>>>
>>>     type filter hook input priority 0; policy drop;
>>>
>>>     ct state established,related accept
>>>
>>>     iifname "lo" accept
>>>
>>>     ip saddr 192.168.1.0/24 tcp dport 22 accept
>>>
>>>     tcp dport 80 accept
>>>
>>>     tcp dport 443 accept
>>>
>>>   }
>>>
>>>   # outbound traffic - no restrictions
>>>
>>>   chain my_filter_output {
>>>
>>>     type filter hook output priority 0; policy accept;
>>>
>>>   }
>>>
>>>   # forwarded traffic - no restrictions
>>>
>>>   chain my_filter_forward {
>>>
>>>     type filter hook forward priority 0; policy accept;
>>>
>>>   }
>>>
>>>   # NAT required to use this server as a router
>>>
>>>   chain my_nat_postrouting {
>>>
>>>     type nat hook postrouting priority 0; policy accept;
>>>
>>>     ip saddr 192.168.1.0/24 masquerade
>>>
>>>   }
>>>
>>>   # DSCP to give the user at 192.168.1.2 priority over everyone else
>>>
>>>   chain my_route_output {
>>>
>>>     type route hook output priority filter; policy accept;
>>>
>>>     ip saddr 192.168.1.2 ip dscp cs1
>>>
>>>   }
>>>
>>> }
>>>
>>> So you could run "nft flush ruleset; nft -f 
>>> /etc/sysconfig/nftables.conf" to load those rules.
>>>
>>> Another useful command: "nft list ruleset".
>>>
>>>
>>>
>>> On 5/23/2023 12:01 PM, Lou Duchez wrote:
>>>> ... even more efficiency: what happens if, ten minutes after you 
>>>> disable the IPs, you switch to a third ruleset where the IPs are 
>>>> disabled AFTER the "established,related" line? So hopefully all 
>>>> those established connections will have been broken in those ten 
>>>> minutes, and then you can go back to the efficiency of putting 
>>>> "established,related" first.
>>>>
>>>> Side note, I switched to nftables a couple years ago, and I've been 
>>>> very happy with it. There's a learning curve, but it's not that 
>>>> terrible. I don't know that there's any advantage for your 
>>>> particular scenario, but it seems to be what they want us to use 
>>>> instead of iptables, and so it feels like bowing to the inevitable.
>>>>
>>>> On 5/23/2023 11:18 AM, Lou Duchez wrote:
>>>>> Put in the rules to disable the IPs before the 
>>>>> "established,related" line? Normally you want the 
>>>>> "established,related" as the first thing for efficiency's sake, 
>>>>> but if you have to put a couple rules before that, you have to.
>>>>>
>>>>> On 5/23/2023 10:42 AM, Ben Hollingsworth wrote:
>>>>>> I have a somewhat complex IPtables setup (configured via 
>>>>>> fwbuilder) that protects my home network. My firewall box runs 
>>>>>> Ubuntu server 20.04. At a certain hour each night, I block a 
>>>>>> handful of IPs that belong to my children's devices so that they 
>>>>>> can't use them all night. I do this by keeping two separate 
>>>>>> IPtables configs and using cron to install the appropriate one at 
>>>>>> the appropriate time.
>>>>>>
>>>>>> This works fine for blocking new connections, but I've found that 
>>>>>> any connections that happen to be open when the new config is 
>>>>>> loaded will continue to stay open. My kids have figured that out 
>>>>>> as well.
>>>>>>
>>>>>> The problem comes from this line, which exists in both configs, 
>>>>>> and keeps related connections open across my reload:
>>>>>>
>>>>>> $IPTABLES -A FORWARD -m conntrack --ctstate ESTABLISHED,RELATED 
>>>>>> -j ACCEPT
>>>>>>
>>>>>> Is there any way that I can turn off connection tracking for only 
>>>>>> certain IPs? I'd really rather that open connections for 
>>>>>> authorized IPs not get interrupted, but I can live with that if I 
>>>>>> must.
>>>>>>


-- 
*Ben "Obi-Wan" Hollingsworth* obiwan at jedi.com www.Jedi.com 
<http://www.jedi.com>
The stuff of earth competes for the allegiance I owe only to the
Giver of all good things, so if I stand, let me stand on the
promise that You will pull me through. /-- Rich Mullins/


More information about the OLUG mailing list