Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 19 Sep 2025 20:19:08 +0100
From:      Roy Marples <roy@marples.name>
To:        <avg@FreeBSD.org>
Cc:        <freebsd-net@freebsd.org>
Subject:   Re: DHCP on multi-homed host, some thoughts
Message-ID:  <199636a7ff7.6b695ed1462688.6190907331232783668@marples.name>
In-Reply-To: <6abe9da1-9818-438b-ad8f-5424e50a39ce@FreeBSD.org>
References:  <6abe9da1-9818-438b-ad8f-5424e50a39ce@FreeBSD.org>

next in thread | previous in thread | raw e-mail | index | archive | help
------=_Part_3927069_1112315404.1758309548023
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: 7bit

You could look into using dhcpcd from ports which solved this multihome issue years ago.


Each interface automatically get a metric based on type and index. This is override able, lowest wins.
For any competing setup, lowest takes precedence and seamlessly changes when the interface goes down or loses a lease.



Roy






---- On Fri, 19 Sep 2025 20:13:45 +0100 Andriy Gapon <avg@FreeBSD.org> wrote ----





Admittedly not a very common configuration, but still possible and some people 
have it (according to the Internet).  I am also trying to set up such a 
configuration for "reasons". 
 
In the simplest form, there are two network interfaces connected to two 
different networks.  Each network has its own DHCP server, its own router / 
gateway to the wider Internet, its own DNS server(s), etc.  The networks are 
likely to be completely unaware of each other. 
 
The host itself may be a router providing internet access to another local 
network via another interface (or even multiple networks + interfaces).  But 
that's not important. 
 
Some things provided via DHCP are per interface, but others are per host 
("global").  Each interface can get its own IP address, that's fine. 
But, for example, which gateway to select for the default route? 
 
Dealing with those "global" things is the main issue in such a setup. 
 
What do we have now? 
Specifically, with dhclient that's a part of the base. 
 
Essentially, it has a winner takes it all approach. 
That's implemented in the default dhclient-script and the gist of the logic is 
in is_default_interface() function.  Whichever interface is first to get a lease 
with a router wins.  dhclient-script would set the default route to the router 
and as long as the default route goes through the interface, the interface 
remains the winner (for subsequent updates). 
 
So, the winner gets to set the default route. 
The winner also gets to set the resolver configuration (using resolvconf(8), by 
default). 
Losers can only configure their interface, other information is lost. 
 
If DHCP is simply configured for multiple interfaces via rc.conf, without any 
extra settings, then there is an obvious problem.  A winner would depend on 
random things like which interface gets link first, which DHCP sever is more 
responsive, etc.  And a random winner is not always what is desired. 
 
As far as I know, there is no way to set any priority or anything like that. 
I found only two solutions used by other people, both not ideal. 
 
One solution is to start dhclient-s "manually" (i.e., outside of rc.conf 
declarative configuration) via something like rc.local.  This way we can control 
which interface gets configured first. 
 
The other approach is to create a dhclient.conf configuration for the 
"secondary" interface(s) which would ignore the "global" options (routers, name 
servers, etc).  This way the "primary" interface would be the only one that gets 
and sets the global configuration while all interfaces get their individual IP 
configuration. 
 
The latter approach is "less intrusive" (more declarative), but it has a flaw 
that if the selected primary network is down then there would be no default 
route at all. 
 
Both solutions still have the issue of discarding the global options from the 
secondary interface (either explicitly in dhclient.conf or by dhclient-script's 
strategy).  And those options may come handy if we want to dynamically flip (and 
as seamlessly as possible) between interfaces based on some events / criteria. 
 
It's especially interesting that dhclient uses the power of resolvconf(8) 
(unless forced to update /etc/resolv.conf directly) but still takes only the 
winner's configuration. 
I think that it could just add configurations from all interfaces and let 
resolvconf(8) deal with that.  And an administrator would have control over how 
multiple configurations are merged via resolvconf.conf.  Especially, if a local 
resolver (like unbound, for instance) is used.  E.g., it would be possible to 
use different name servers based on domain, etc. 
 
Regarding routing, these days we can have multiple FIBs, so instead of 
discarding "secondary" routing information we could use it to configure a 
non-default FIB. 
 
Initially, I wanted to start working on some changes to dhclient-script to 
implement those ideas.  But then it occurred to me that it would easier to get 
what I want by changes external to dhclient. 
 
If there was a way to run a secondary dhclient with a non-default FIB (e.g., via 
setfib) then that alone would achieve the goals: 
- the secondary dhclient would be considered a winner because it's the only one 
to set the default route of the FIB; 
- so, it would obviously set the default route in the FIB; 
- and because the dhclient is considered a winner, it would also call resolvconf. 
 
I wonder if it would be a good idea to run dhclient under setfib if an interface 
is configured with DHCP/DHCPSYNC "virtual" option and real ifconfig 'fib' option. 
Or would that clash with some other uses / intentions? 
Then maybe we could add another virtual option like FIB<X> or DHCPFIB<X>? 
Or, probably even better, some thing like dhclient_fib_IF=X? 
Akin to background_dhclient, for example. 
 
The standard dhclient_fib option is, obviously, of no use because it would put 
all dhclient-s into the same FIB. 
 
-- 
Andriy Gapon
------=_Part_3927069_1112315404.1758309548023
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html><head>=
<meta content=3D"text/html;charset=3DUTF-8" http-equiv=3D"Content-Type"></h=
ead><body ><div style=3D"font-family: Verdana; font-size: 11pt;"><div>You c=
ould look into using dhcpcd from ports which solved this multihome issue ye=
ars ago.</div><div><br></div><div>Each interface automatically get a metric=
 based on type and index. This is override able, lowest wins.</div><div>For=
 any competing setup, lowest takes precedence and seamlessly changes when t=
he interface goes down or loses a lease.<br></div><div><br></div><div id=3D=
"signatureElementId" style=3D"display: block;"><div>Roy</div></div><div><br=
></div><div><div><br><br></div><div class=3D"replyHeader">---- On Fri, 19 S=
ep 2025 20:13:45 +0100 <b>Andriy Gapon &lt;avg@FreeBSD.org&gt;</b> wrote --=
--<br></div><div><br></div><blockquote style=3D"margin:0 0 0 0"><div><br><b=
r>Admittedly not a very common configuration, but still possible and some p=
eople <br>have it (according to the Internet).  I am also trying to set up =
such a <br>configuration for "reasons". <br> <br>In the simplest form, ther=
e are two network interfaces connected to two <br>different networks.  Each=
 network has its own DHCP server, its own router / <br>gateway to the wider=
 Internet, its own DNS server(s), etc.  The networks are <br>likely to be c=
ompletely unaware of each other. <br> <br>The host itself may be a router p=
roviding internet access to another local <br>network via another interface=
 (or even multiple networks + interfaces).  But <br>that's not important. <=
br> <br>Some things provided via DHCP are per interface, but others are per=
 host <br>("global").  Each interface can get its own IP address, that's fi=
ne. <br>But, for example, which gateway to select for the default route? <b=
r> <br>Dealing with those "global" things is the main issue in such a setup=
. <br> <br>What do we have now? <br>Specifically, with dhclient that's a pa=
rt of the base. <br> <br>Essentially, it has a winner takes it all approach=
. <br>That's implemented in the default dhclient-script and the gist of the=
 logic is <br>in is_default_interface() function.  Whichever interface is f=
irst to get a lease <br>with a router wins.  dhclient-script would set the =
default route to the router <br>and as long as the default route goes throu=
gh the interface, the interface <br>remains the winner (for subsequent upda=
tes). <br> <br>So, the winner gets to set the default route. <br>The winner=
 also gets to set the resolver configuration (using resolvconf(8), by <br>d=
efault). <br>Losers can only configure their interface, other information i=
s lost. <br> <br>If DHCP is simply configured for multiple interfaces via r=
c.conf, without any <br>extra settings, then there is an obvious problem.  =
A winner would depend on <br>random things like which interface gets link f=
irst, which DHCP sever is more <br>responsive, etc.  And a random winner is=
 not always what is desired. <br> <br>As far as I know, there is no way to =
set any priority or anything like that. <br>I found only two solutions used=
 by other people, both not ideal. <br> <br>One solution is to start dhclien=
t-s "manually" (i.e., outside of rc.conf <br>declarative configuration) via=
 something like rc.local.  This way we can control <br>which interface gets=
 configured first. <br> <br>The other approach is to create a dhclient.conf=
 configuration for the <br>"secondary" interface(s) which would ignore the =
"global" options (routers, name <br>servers, etc).  This way the "primary" =
interface would be the only one that gets <br>and sets the global configura=
tion while all interfaces get their individual IP <br>configuration. <br> <=
br>The latter approach is "less intrusive" (more declarative), but it has a=
 flaw <br>that if the selected primary network is down then there would be =
no default <br>route at all. <br> <br>Both solutions still have the issue o=
f discarding the global options from the <br>secondary interface (either ex=
plicitly in dhclient.conf or by dhclient-script's <br>strategy).  And those=
 options may come handy if we want to dynamically flip (and <br>as seamless=
ly as possible) between interfaces based on some events / criteria. <br> <b=
r>It's especially interesting that dhclient uses the power of resolvconf(8)=
 <br>(unless forced to update /etc/resolv.conf directly) but still takes on=
ly the <br>winner's configuration. <br>I think that it could just add confi=
gurations from all interfaces and let <br>resolvconf(8) deal with that.  An=
d an administrator would have control over how <br>multiple configurations =
are merged via resolvconf.conf.  Especially, if a local <br>resolver (like =
unbound, for instance) is used.  E.g., it would be possible to <br>use diff=
erent name servers based on domain, etc. <br> <br>Regarding routing, these =
days we can have multiple FIBs, so instead of <br>discarding "secondary" ro=
uting information we could use it to configure a <br>non-default FIB. <br> =
<br>Initially, I wanted to start working on some changes to dhclient-script=
 to <br>implement those ideas.  But then it occurred to me that it would ea=
sier to get <br>what I want by changes external to dhclient. <br> <br>If th=
ere was a way to run a secondary dhclient with a non-default FIB (e.g., via=
 <br>setfib) then that alone would achieve the goals: <br>- the secondary d=
hclient would be considered a winner because it's the only one <br>to set t=
he default route of the FIB; <br>- so, it would obviously set the default r=
oute in the FIB; <br>- and because the dhclient is considered a winner, it =
would also call resolvconf. <br> <br>I wonder if it would be a good idea to=
 run dhclient under setfib if an interface <br>is configured with DHCP/DHCP=
SYNC "virtual" option and real ifconfig 'fib' option. <br>Or would that cla=
sh with some other uses / intentions? <br>Then maybe we could add another v=
irtual option like FIB&lt;X&gt; or DHCPFIB&lt;X&gt;? <br>Or, probably even =
better, some thing like dhclient_fib_IF=3DX? <br>Akin to background_dhclien=
t, for example. <br> <br>The standard dhclient_fib option is, obviously, of=
 no use because it would put <br>all dhclient-s into the same FIB. <br> <br=
>-- <br>Andriy Gapon <br> <br> <br></div></blockquote></div><div><br></div>=
</div><br></body></html>
------=_Part_3927069_1112315404.1758309548023--




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199636a7ff7.6b695ed1462688.6190907331232783668>