From 1b77ea85220dd9a93d1048e50ed8360d87e0b06a Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Fri, 19 Feb 2010 19:31:50 +0100 Subject: [PATCH] added the "type" parameter to @resolve() Support DNS record types A, AAAA, NS, MX. --- NEWS | 1 + doc/ferm.pod | 7 ++++--- examples/resolve.ferm | 6 ++++++ src/ferm | 24 ++++++++++++++++++------ 4 files changed, 29 insertions(+), 9 deletions(-) diff --git a/NEWS b/NEWS index 611c645..af21582 100644 --- a/NEWS +++ b/NEWS @@ -10,6 +10,7 @@ v2.0.8 - not yet released - added automatic variable $DIRNAME - implement confirmation/rollback for --shell --interactive + - added the "type" parameter to @resolve() v2.0.7 - 2 Jan 2010 diff --git a/doc/ferm.pod b/doc/ferm.pod index 4c17d3e..b9ec488 100644 --- a/doc/ferm.pod +++ b/doc/ferm.pod @@ -1603,20 +1603,21 @@ hooks. There are several built-in functions which you might find useful. -=head2 @resolve((hostname1 hostname2 ...)) +=head2 @resolve((hostname1 hostname2 ...), [type]) Usually, host names are resolved by iptables. To let ferm resolve host names, use the function @resolve: saddr @resolve(my.host.foo) proto tcp dport ssh ACCEPT; saddr @resolve((another.host.foo third.host.foo)) proto tcp dport openvpn ACCEPT; + daddr @resolve(ipv6.google.com, AAAA) proto tcp dport http ACCEPT; Note the double parentheses in the second line: the inner pair for creating a ferm list, and the outer pair as function parameter delimiters. -This function currently only resolves B records (i.e. IPv4 -addresses), rendering it useless for the I domain. +The second parameter is optional, and specifies the DNS record type. +The default is "A". Be careful with resolved host names in firewall configuration. DNS requests may block the firewall configuration for a long time, leaving diff --git a/examples/resolve.ferm b/examples/resolve.ferm index ca84576..c719379 100644 --- a/examples/resolve.ferm +++ b/examples/resolve.ferm @@ -9,4 +9,10 @@ table filter chain OUTPUT { daddr @resolve(www.google.com) proto tcp dport http ACCEPT; + daddr @resolve(yahoo.com, MX) proto tcp dport smtp ACCEPT; + daddr @resolve(denic.de, NS) proto udp dport domain ACCEPT; +} + +domain ip6 table filter chain OUTPUT { + daddr @resolve(www.sixxs.net, AAAA) proto tcp dport http ACCEPT; } diff --git a/src/ferm b/src/ferm index 2487dfe..55662b2 100755 --- a/src/ferm +++ b/src/ferm @@ -954,11 +954,23 @@ sub resolve($\@$) { foreach my $rr ($query->answer) { next unless $rr->type eq $type; - push @result, $rr->address; + + if ($type eq 'NS') { + push @result, $rr->nsdname; + } elsif ($type eq 'MX') { + push @result, $rr->exchange; + } else { + push @result, $rr->address; + } } } - return \@result; + # NS/MX records return host names; resolve these again in the + # second pass (IPv4 only currently) + @result = resolve($resolver, \@result, 'A') + if $type eq 'NS' or $type eq 'MX'; + + return @result; } # returns the next parameter, which may either be a scalar or an array @@ -1069,15 +1081,15 @@ sub getvalues { } elsif ($token =~ /^@/) { if ($token eq '@resolve') { my @params = get_function_params(); - error('Usage: @resolve((hostname ...))') - unless @params == 1; + error('Usage: @resolve((hostname ...), [type])') + unless @params == 1 or @params == 2; eval { require Net::DNS; }; error('For the @resolve() function, you need the Perl library Net::DNS') if $@; - my $type = 'A'; + my $type = $params[1] || 'A'; my $resolver = new Net::DNS::Resolver; my @params = to_array($params[0]); - return resolve($resolver, @params, $type); + return [resolve($resolver, @params, $type)]; } else { error("unknown ferm built-in function"); } -- 2.11.4.GIT