Re: Possible to check if ip daddr belongs to an interface in the prerouting chain?

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Sun, 30 Apr 2023 19:54:22 +0800
Glen Huang <heyhgl@xxxxxxxxx> wrote:

> Hey Kerin,
> 
> Do you mind if I ask a follow up question?
> 
> I gave the two rules you listed some more thoughts, and I still puzzle over a small detail:
> 
> It seems the tuple can change the meaning of the type value? For example, "fib daddr type local”, matches packets destine to any local interfaces, so “local” means local to the host, whereas "daddr . iif type local” matches packets destine to the interface they arrive, so “local” means local to the iif. I thought the type value’s meaning was absolute?

You are quite right. Given that this kind of check always 'returns' a fib_addrtype, the stricter form of the check does entail munging its value. Taking "daddr . iif" as an example, in the case that the destination address is a unicast address that does not belong to the specified interface, the value will be 1 (unicast) instead of 2 (local), even though it technically is a local address.

> 
> I also checked man ip route, and it described local route type as 
> 
> > the destinations are assigned to this host. The packets are looped back and delivered locally.
> 
> So it seems "daddr . iif” now changes it to "the destinations are assigned to the incoming interface”. Are there other values that can have different meanings for different tuples?

FIB expressions performing reverse path checks spring to mind. Below are four (equivalent) rules that perform strict reverse path filtering. The value of "oif" can be compared to either 0 (missing) or 1 (exists).

  fib saddr . iif oif 0          drop comment "strict uRPF filtering"
  fib saddr . iif oif == 0       drop comment "strict uRPF filtering"
  fib saddr . iif oif missing    drop comment "strict uRPF filtering"
  fib saddr . iif oif == missing drop comment "strict uRPF filtering"

If "iif" is removed from the tuple then the value can be 0 (missing) or any value greater than 0, in which case it can be taken to be an interface index. The following four rules implement loose reverse path filtering in much the same fashion as setting rp_filter = 2 does [1].

  fib saddr oif 0          drop comment "loose uRPF filtering"
  fib saddr oif == 0       drop comment "loose uRPF filtering"
  fib saddr oif missing    drop comment "loose uRPF filtering"
  fib saddr oif == missing drop comment "loose uRPF filtering"

Now, let's say that I have an interface named "eth0" and that it currently has an iface_index of 4.

  $ cat /sys/class/net/eth0/ifindex
  4

In that case, both of the following rules would drop packets other than those for which the route to the source address would entail the traversal of eth0.

  fib saddr oif != 4 drop
  fib saddr oif != "eth0" drop

The only difference is that, for the second rule, nft must resolve the ifname to an iface_index in the course of translating and applying the rule. Incidentally, such rules need to be defined within the scope of a prerouting hook; acting otherwise may result in cryptic errors.

[1] https://www.kernel.org/doc/html/latest/networking/ip-sysctl.html

-- 
Kerin Millar



[Index of Archives]     [Linux Netfilter Development]     [Linux Kernel Networking Development]     [Netem]     [Berkeley Packet Filter]     [Linux Kernel Development]     [Advanced Routing & Traffice Control]     [Bugtraq]

  Powered by Linux