Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unbound: local-data except IPv6 GA addresses with odhcpd #25954 #25975

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions net/unbound/files/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,7 @@ One instance is supported currently.
| validator | 0 | boolean | Enable DNSSEC validator module. | module: validator |
| validator_ntp | 1 | boolean | Disable DNSSEC time checks at boot and restart when NTP locks in time. DNSSEC requires time validation and this breaks the chicken and egg. | - |
| verbosity | 1 | level | Logging inensity. | verbosity: |
| exclude_ipv6_ga | 0 | boolean | If exclude IPv6 global addresses from local data. | local-data: |

### config zone
Confingure any mix of Unbound `forward-zone:`, `stub-zone:`, or `auth-zone:` clauses. These sections are more compact than Unbound and will unroll into Unbound's configuration syntax.
Expand Down
84 changes: 66 additions & 18 deletions net/unbound/files/odhcpd.awk
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
# "bslaac" = boolean, use DHCPv4 MAC to find GA and ULA IPV6 SLAAC
# "bisolt" = boolean, format <host>.<network>.<domain>. so you can isolate
# "bconf" = boolean, write conf file with pipe records
# "exclude_ipv6_ga" = boolean, exclude IPv6 GA addresses from local-data
#
##############################################################################

Expand All @@ -38,16 +39,14 @@
sub( /.*\//, "", cdr2 ) ;
gsub( /_/, "-", hst ) ;


if ( hst !~ /^[[:alnum:]]([-[:alnum:]]*[[:alnum:]])?$/ ) {
# that is not a valid host name (RFC1123)
# above replaced common error of "_" in host name with "-"
hst = "-" ;
}


if ( bisolt == 1 ) {
# TODO: this might be better with a substituion option,
# TODO: this might be better with a substitution option,
# or per DHCP pool do-not-DNS option, but its getting busy here.
fqdn = net
gsub( /\./, "-", fqdn ) ;
Expand All @@ -58,56 +57,52 @@
fqdn = tolower( hst "." domain ) ;
}


if ((cls == "ipv4") && (hst != "-") && (cdr == 32) && (NF == 9)) {
# IPV4 ; only for provided hostnames and full /32 assignments
# NF=9 ; odhcpd errata in field format without host name
ptr = adr ; qpr = "" ; split( ptr, ptrarr, "." ) ;
slaac = slaac_eui64( id ) ;


if ( bconf == 1 ) {
x = ( "local-data: \"" fqdn ". 300 IN A " adr "\"" ) ;
y = ( "local-data-ptr: \"" adr " 300 " fqdn "\"" ) ;
print ( x "\n" y "\n" ) > conffile ;
}


# always create the pipe file
for( i=1; i<=4; i++ ) { qpr = ( ptrarr[i] "." qpr) ; }
x = ( fqdn ". 300 IN A " adr ) ;
y = ( qpr "in-addr.arpa. 300 IN PTR " fqdn ) ;
print ( x "\n" y ) > pipefile ;


if (( bslaac == 1 ) && ( slaac != 0 )) {
# UCI option to discover IPV6 routed SLAAC addresses
# NOT TODO - ping probe take too long when added in awk-rule loop
cmd = ( "ip -6 --oneline route show dev " net ) ;


while ( ( cmd | getline adr ) > 0 ) {
if (( substr( adr, 1, 5 ) <= "fdff:" ) \
&& ( index( adr, "::/" ) != 0 ) \
&& ( index( adr, "anycast" ) == 0 ) \
&& ( index( adr, "via" ) == 0 )) {
# GA or ULA routed addresses only (not LL or MC)
if ( exclude_ipv6_ga == 1 && ipv6_in_range(adr) ) {
printf "Excluding GA IPv6 address: %s for %s\n", \
adr, fqdn | "logger -t unbound-odhcpd"
continue
}
sub( /\/.*/, "", adr ) ;
adr = ( adr slaac ) ;


if ( split( adr, tmp0, ":" ) > 8 ) {
sub( "::", ":", adr ) ;
}


if ( bconf == 1 ) {
x = ( "local-data: \"" fqdn ". 300 IN AAAA " adr "\"" ) ;
y = ( "local-data-ptr: \"" adr " 300 " fqdn "\"" ) ;
print ( x "\n" y "\n" ) > conffile ;
}


# always create the pipe file
qpr = ipv6_ptr( adr ) ;
x = ( fqdn ". 300 IN AAAA " adr ) ;
Expand All @@ -116,41 +111,50 @@
}
}


close( cmd ) ;
}
}

else if ((cls != "ipv4") && (hst != "-") && (9 <= NF) && (NF <= 10)) {
if (cdr == 128) {
if ( exclude_ipv6_ga == 1 && ipv6_in_range(adr) ) {
printf "Excluding GA IPv6 address: %s for %s\n", \
adr, fqdn | "logger -t unbound-odhcpd"
}
else {
if ( bconf == 1 ) {
x = ( "local-data: \"" fqdn ". 300 IN AAAA " adr "\"" ) ;
y = ( "local-data-ptr: \"" adr " 300 " fqdn "\"" ) ;
print ( x "\n" y "\n" ) > conffile ;
}


# only for provided hostnames and full /128 assignments
qpr = ipv6_ptr( adr ) ;
x = ( fqdn ". 300 IN AAAA " adr ) ;
y = ( qpr ". 300 IN PTR " fqdn ) ;
print ( x "\n" y ) > pipefile ;
}
}

if (cdr2 == 128) {
if ( exclude_ipv6_ga == 1 && ipv6_in_range(adr2) ) {
printf "Excluding GA IPv6 address: %s for %s\n", \
adr2, fqdn | "logger -t unbound-odhcpd"
}
else {
if ( bconf == 1 ) {
x = ( "local-data: \"" fqdn ". 300 IN AAAA " adr2 "\"" ) ;
y = ( "local-data-ptr: \"" adr2 " 300 " fqdn "\"" ) ;
print ( x "\n" y "\n" ) > conffile ;
}


# odhcp puts GA and ULA on the same line (position 9 and 10)
qpr2 = ipv6_ptr( adr2 ) ;
x = ( fqdn ". 300 IN AAAA " adr2 ) ;
y = ( qpr2 ". 300 IN PTR " fqdn ) ;
print ( x "\n" y ) > pipefile ;
}
}
}

else {
Expand All @@ -164,7 +168,6 @@ function ipv6_ptr( ipv6, arpa, ary, end, m, n, new6, sz, start ) {
# IPV6 colon flexibility is a challenge when creating [ptr].ip6.arpa.
sz = split( ipv6, ary, ":" ) ; end = 9 - sz ;


for( m=1; m<=sz; m++ ) {
if( length(ary[m]) == 0 ) {
for( n=1; n<=end; n++ ) { ary[m] = ( ary[m] "0000" ) ; }
Expand All @@ -175,7 +178,6 @@ function ipv6_ptr( ipv6, arpa, ary, end, m, n, new6, sz, start ) {
}
}


new6 = ary[1] ;
for( m = 2; m <= sz; m++ ) { new6 = ( new6 ary[m] ) ; }
start = length( new6 ) ;
Expand Down Expand Up @@ -203,9 +205,55 @@ function slaac_eui64( mac, ary, glbit, eui64 ) {
eui64 = 0 ;
}


return eui64 ;
}

##############################################################################

function normalize_ipv6(ip, parts, normalized) {
# Remove any prefix length
sub(/\/.*/, "", ip);

# Handle compressed notation (::)
if (index(ip, "::") > 0) {
split(ip, parts, "::");
# Count colons to determine how many zero groups to insert
gsub(/:/, ":", parts[1]);
if (parts[2] != "") gsub(/:/, ":", parts[2]);
missing = 8 - (split(parts[1], tmp1, ":") + split(parts[2], tmp2, ":"));

# Build normalized address
normalized = parts[1];
for (i = 0; i < missing; i++) normalized = normalized ":0";
if (parts[2] != "") normalized = normalized ":" parts[2];
} else {
normalized = ip;
}

# Fill each group with leading zeros
split(normalized, parts, ":");
normalized = "";
for (i = 1; i <= length(parts); i++) {
if (parts[i] == "") parts[i] = "0";
while (length(parts[i]) < 4) {
parts[i] = "0" parts[i];
}
if (i > 1) normalized = normalized ":";
normalized = normalized parts[i];
}

return normalized;
}

function ipv6_in_range(ip) {
# Normalize the address first
ip = normalize_ipv6(ip);

# Check if it's in 2000::/3 range
# This covers 2000:: to 3fff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
first_group = substr(ip, 1, 4);
first_digit = substr(first_group, 1, 1);

return (first_digit == "2" || first_digit == "3");
}

14 changes: 9 additions & 5 deletions net/unbound/files/odhcpd.sh
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,12 @@ odhcpd_zonedata() {
local dhcp4_slaac6=$( uci_get unbound.@unbound[0].dhcp4_slaac6 )
local dhcp_domain=$( uci_get unbound.@unbound[0].domain )
local dhcp_origin=$( uci_get dhcp.@odhcpd[0].leasefile )
local exclude_ipv6_ga=$( uci_get unbound.@unbound[0].exclude_ipv6_ga )

if [ "$exclude_ipv6_ga" != "0" ] && [ "$exclude_ipv6_ga" != "1" ]; then
logger -t unbound -s "invalid exclude_ipv6_ga value, using default (0)"
exclude_ipv6_ga=0
fi

if [ -f "$UB_TOTAL_CONF" ] && [ -f "$dhcp_origin" ] \
&& [ "$dhcp_link" = "odhcpd" ] && [ -n "$dhcp_domain" ] ; then
Expand All @@ -49,7 +54,6 @@ odhcpd_zonedata() {
local dns_ls_old=$UB_VARDIR/dhcp_dns.old
local dhcp_ls_new=$UB_VARDIR/dhcp_lease.new


if [ ! -f $UB_DHCP_CONF ] || [ ! -f $dns_ls_old ] ; then
# no old files laying around
touch $dns_ls_old
Expand All @@ -61,7 +65,6 @@ odhcpd_zonedata() {
dateconf=$(( $( date +%s ) - $( date -r $UB_DHCP_CONF +%s ) ))
dateoldf=$(( $( date +%s ) - $( date -r $dns_ls_old +%s ) ))


if [ $dateconf -gt 300 ] ; then
touch $dns_ls_old
sort $dhcp_origin > $dhcp_ls_new
Expand All @@ -82,7 +85,7 @@ odhcpd_zonedata() {
freshstart)
awk -v conffile=$UB_DHCP_CONF -v pipefile=$dns_ls_new \
-v domain=$dhcp_domain -v bslaac=$dhcp4_slaac6 \
-v bisolt=0 -v bconf=1 \
-v bisolt=0 -v bconf=1 -v exclude_ipv6_ga=$exclude_ipv6_ga \
-f /usr/lib/unbound/odhcpd.awk $dhcp_ls_new

cp $dns_ls_new $dns_ls_add
Expand All @@ -94,7 +97,7 @@ odhcpd_zonedata() {
longtime)
awk -v conffile=$UB_DHCP_CONF -v pipefile=$dns_ls_new \
-v domain=$dhcp_domain -v bslaac=$dhcp4_slaac6 \
-v bisolt=0 -v bconf=1 \
-v bisolt=0 -v bconf=1 -v exclude_ipv6_ga=$exclude_ipv6_ga \
-f /usr/lib/unbound/odhcpd.awk $dhcp_ls_new

awk '{ print $1 }' $dns_ls_old | sort | uniq > $dns_ls_del
Expand All @@ -110,7 +113,7 @@ odhcpd_zonedata() {
# unbound-control can be slow so high DHCP rates cannot run a full list
awk -v conffile=$UB_DHCP_CONF -v pipefile=$dns_ls_new \
-v domain=$dhcp_domain -v bslaac=$dhcp4_slaac6 \
-v bisolt=0 -v bconf=0 \
-v bisolt=0 -v bconf=0 -v exclude_ipv6_ga=$exclude_ipv6_ga \
-f /usr/lib/unbound/odhcpd.awk $dhcp_ls_new

sort $dns_ls_new $dns_ls_old $dns_ls_old | uniq -u > $dns_ls_add
Expand All @@ -136,3 +139,4 @@ if flock -x -n 1000 ; then
fi

##############################################################################

1 change: 1 addition & 0 deletions net/unbound/files/unbound.uci
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ config unbound 'ub_main'
list iface_trig 'wan'
list iface_wan 'wan'
#list domain_insecure 'ntp.example.com'
option exclude_ipv6_ga '0'

config zone 'auth_icann'
# cache the root zone all at once to speed up recursion
Expand Down
Loading