[Ferm] Dual-stacking and IP in variables

Kiss Gabor (Bitman) kissg at ssg.ki.iif.hu
Wed Jul 6 07:15:57 CEST 2011


> In a perfect world, the call sites should just call
>     &ALLOW(tcp, ssh, $TRUSTED);
> and be done with it for both address families.
> 
> Unfortunately, I haven't been able to find a way to do this.
> 
> Thinking of things that /could/ be implemented, I can think of multiple
> approaches that could be used, like:
> 
>   1. Have $TRUSTED = (128.66.1.0/24 2001:db8:456::/48); code the
>      function to ignore the addresses not concering their domain
>      (e.g. by having a built-in that can answer on the validity of an
>      address)
> 
>   2. Same as (1), but have *ferm* ignore statements that are for e.g. an
>      ip6 domain but contain an IPv4 address/subnet in saddr.
> 
>   3. Have $TRUSTED and &ALLOW() set conditionally per domain.
>      Note that contrary to intuition, stanzas like:
>         domain ip  { @def $TRUSTED = (128.66.1.0/24);     }
>         domain ip6 { @def $TRUSTED = (2001:db8:456::/48); }
>      do not work due to scoping limitations of ferm, i.e. $TRUSTED is
>      not defined outside of the domain { } stanza. Same applies for:
>         @if @eq($DOMAIN, ip6) { ? } @else { ? }
>      and other variations I could think of, including messing with @include
>      to bypass the scoping limitations.
> 
> I had a quick glance at the code and it seems that all of the above are
> quite difficult to implement without some major restructuring.
> 
> Any other ideas? Am I missing something obvious?


First of all two built-in functions are required.
One for IPv4 and the other for IPv6.

SELECT4(addrlist) checks its arguments - domain names and IP
addresses - and returns a list of IPv4 ones.
I.e. drops pure IPv6 addresses and those domain names that
has no "A" record.

SELECT6(addrlist) is similar.
Returns items acceptable by ip6tables.

E.g.

def $TRUSTED = (
	66.117.47.214
	2001:4810::110
	whatismyv6.com
	ipv4.whatismyv6.com
	ipv6.whatismyv6.com
);

SELECT4(($TRUSTED)) returns
(66.117.47.214 whatismyv6.com ipv4.whatismyv6.com)

SELECT6(($TRUSTED)) returns
(2001:4810::110 whatismyv6.com ipv6.whatismyv6.com)

Yes I know this requires DNS queries. But this way ferm can
abandon domain names that would be refused by iptables/ip6tables.

Now it is easy to write mixed domain functions:

@def &ALLOW($proto,$port,$addrlist) = {
	@if @eq($DOMAIN, ip) {
		ALLOW proto $proto dport $port saddr (SELECT4($addrlist));
	}
	@if @eq($DOMAIN, ip6) {
		ALLOW proto $proto dport $port saddr (SELECT6($addrlist));
	}
}

Or similar.

What is your opinion?

Cheers

Gabor
-- 
Wenn ist das Nunstück git und Slotermeyer?
Ja! ... Beiherhund das Oder die Flipperwaldt gersput.


More information about the Ferm mailing list