Environment
- Version: 1.25.0
- Configuration:
infra-host-ttl: 900, infra-cache-max-rtt: 120000, infra-keep-probing: no (defaults)
- OS: Ubuntu 22.04.5 LTS
Background
- Unbound lost outbound internet access for ~10 minutes due to infrastructure issues
- During this period upstream servers reached
rto = 120000 (infra-cache-max-rtt)
- Connectivity was restored, SERVFAILs stopped, unbound resumed normal operation
- After 5 days unbound still have
expired rto 120000 state for 11 of 13 root servers, so unbound only queries 2 of them. Root servers are used here as the most visible example, the same situation for any zone
$ unbound-control dump_infra | grep " \. "
2a02:5501:0:6000::c707:5b0d . ttl 577 ping 16 var 53 rtt 228 rto 228 tA 0 tAAAA 0 tother 0 ednsknown 1 edns 0 delay 0 lame dnssec 0 rec 0 A 0 other 0
2a02:5501:0:6000::ca0c:1b21 . expired rto 120000
2a02:5501:0:6000::c661:be35 . expired rto 120000
2a02:5501:0:6000::c03a:801e . expired rto 120000
2a02:5501:0:6000::c070:2404 . expired rto 120000
2a02:5501:0:6000::c024:9411 . expired rto 120000
2a02:5501:0:6000::c005:5f1 . expired rto 120000
2a02:5501:0:6000::c021:40c . expired rto 120000
2a02:5501:0:6000::c100:e81 . ttl 577 ping 23 var 65 rtt 283 rto 1132 tA 2 tAAAA 0 tother 0 ednsknown 1 edns 0 delay 0 lame dnssec 0 rec 0 A 0 other 0
2a02:5501:0:6000::aaf7:aa02 . expired rto 120000
2a02:5501:0:6000::c707:532a . expired rto 120000
2a02:5501:0:6000::c629:4 . expired rto 120000
2a02:5501:0:6000::c0cb:e60a . expired rto 120000
Actual behavior
No automatic recovery. infra_get_lame_rtt() assigns sel_rtt = 119000 ms to expired entries. iter_server_selection only considers servers within RTT_BAND = 400 ms of the best live server, so expired servers never enter the candidate pool -> never probed -> never recovers.
Issues:
- After the internet was restored, unbound randomly selected some server, but only some of them
- Selected servers are not necessarily the fastest
- Other servers do not participate in DNS resolution - there is no balancing between upstreams
- Monitoring is difficult - we don't have statistics on other upstreams
Setting infra-keep-probing: yes was tested both at runtime via unbound-control set_option and locally from the start in config.
With the option enabled, SERVFAILs stopped during the outage once all servers hit rto = 120000; unbound kept sending single probe queries instead of failing immediately.
However, after connectivity was restored, servers with expired rto 120000 still did not recover over time.
Proposed fix
-
Active background probing of expired entries independent of query selection. Fix what infra-keep-probing was intended to do but currently doesn't.
-
Modify infra_get_lame_rtt() to return UNKNOWN_SERVER_NICENESS instead of still_useful_timeout() for expired records with max rto. This makes them fit within RTT_BAND and periodically receive queries, naturally triggering recovery.
Workaround
Flush infra cache:
unbound-control flush_infra all
But this is manual action, not a solution. I think that self-healing is expected behavior and should work without any manual actions
Environment
infra-host-ttl: 900,infra-cache-max-rtt: 120000,infra-keep-probing: no(defaults)Background
rto = 120000(infra-cache-max-rtt)expired rto 120000state for 11 of 13 root servers, so unbound only queries 2 of them. Root servers are used here as the most visible example, the same situation for any zoneActual behavior
No automatic recovery.
infra_get_lame_rtt()assignssel_rtt = 119000 msto expired entries.iter_server_selectiononly considers servers withinRTT_BAND = 400 msof the best live server, so expired servers never enter the candidate pool -> never probed -> never recovers.Issues:
Setting
infra-keep-probing: yeswas tested both at runtime viaunbound-control set_optionand locally from the start in config.With the option enabled, SERVFAILs stopped during the outage once all servers hit
rto = 120000; unbound kept sending single probe queries instead of failing immediately.However, after connectivity was restored, servers with
expired rto 120000still did not recover over time.Proposed fix
Active background probing of expired entries independent of query selection. Fix what
infra-keep-probingwas intended to do but currently doesn't.Modify
infra_get_lame_rtt()to returnUNKNOWN_SERVER_NICENESSinstead ofstill_useful_timeout()for expired records with max rto. This makes them fit withinRTT_BANDand periodically receive queries, naturally triggering recovery.Workaround
Flush infra cache:
But this is manual action, not a solution. I think that self-healing is expected behavior and should work without any manual actions