This commit add the ability for ctrld to gather client information,
including mac/ip/hostname, and send to Control-D server through a
config per upstream.
- Add send_client_info upstream config.
- Read/Watch dnsmasq leases files on supported platforms.
- Add corresponding client info to DoH query header
All of these only apply for Control-D upstream, though.
So we don't have to depend on network stack probing to decide whether
ipv4 or ipv6 will be used.
While at it, also prevent a race report when doing the same parallel
resolving for os resolver, even though this race is harmless.
Otherwise, we experiment with ctrld slow start after rebooting, because
the network check continuously report failed status even the network
state is up. Restoring the DNS before stopping, we leave the network
state as default, as long as ctrld starts, the DNS is configured again.
The bootstrap process has two issues that can make ctrld stop resolving
after restarting machine host.
ctrld uses bootstrap DNS and os nameservers for resolving upstream. On
unix, /etc/resolv.conf content is used to get available nameservers.
This works well when installing ctrld. However, after being installed,
ctrld may modify the content of /etc/resolv.conf itself, to make other
apps use its listener as DNS resolver. So when ctrld starts after OS
restart, it ends up using [bootstrap DNS + ctrld's listener], for
resolving upstream. At this moment, if ctrld could not contact bootstrap
DNS for any reason, upstream domain will not be resolved.
For above reason, an upstream may not have bootstrap IPs after ctrld
starts. When re-bootstrapping, if there's no bootstrap IPs, ctrld should
call the setup bootstrap process again. Currently, it does not, causing
all queries failed.
This commit fixes above issue by adding mechanism for retrieving OS
nameservers properly, by querying routing table information:
- Parsing /proc/net subsystem on Linux.
- For BSD variants, just fetching routing information base from OS.
- On Windows, just include the gateway information when reading iface.
The fixing for second issue is trivial, just kickoff a bootstrap process
if there's no bootstrap IPs when re-boostrapping.
While at it, also ensure that fetching resolver information from
ControlD API is also used the same approach.
Fixes#34
For os resolver, ctrld queries against all servers concurrently, and get
the first success result back. However, if all server failed, the result
channel is not closed, causing ctrld hang.
Fixing this by closing the result channel once getting back all response
from servers.
While at it, also shorten the backoff time when waiting for network up,
ctrld should serve as fast as possible after network is available.
Updates #34
- Include version/OS information when logging
- Make time field human readable in log file
- Force root privilege when running status command on darwin
Updates #34
When startup, ctrld waits for network up before calling s.Run to starts
its logic. However, if network is down on startup, ctrld will hang on
waiting for network up. That causes OS service manager unhappy, as ctrld
do not response to it, marking ctrld as failure service and never start
ctrld again.
To fix this, we should call s.Run as soon as possible, and use a channel
for waiting a signal that we can actual do our logic after network up.
Update #34
Avoiding reading/writing global config, causing a data race. While at
it, also guarding read/write access to cfg.Service.AllocateIP field,
since when it is read/write by multiple goroutines.
We only need on demand information when re-bootstrapping. On Bootsrap,
this is already checked by ctrldnet.Up, so on demand query will cause
un-necessary slow down if external ipv6 is slow to response.
On Windows host with StarLink network, ctrld hangs on startup for ~30s
before continue running. This dues to IPv6 is configured but no external
IPv6 can be reached. When probing stack, ctrld is dialing using ipv6
without any timeout set, so the dialing timeout is enforced by OS.
This commit adds a timeout for probing dialer, so we ensure the probing
process will fail fast.
So we don't have to worry about network stack changes causes an upstream
to be broken. Just send requests to all nameservers concurrently, and
get the first success response.
Instead of re-query DNS record for upstream when re-bootstrapping, just
query all records on startup, then selecting the next bootstrap ip
depends on the current network stack.
For better recovery and dealing with network stack changes, this commit
change the request flow to:
failure of any kind -> recreate transport/re-bootstrap -> retry once
That would make ctrld recover from all scenarios in theory.
At startup, ctrld gathers bootstrap IP information and use this
bootstrap IP for connecting to upstream. However, in case the network
stack changed, for example, dues to VPN connection, ctrld will still use
this old (maybe invalid) bootstrap IP for the current network stack.
This commit rework the discovering process, and re-initializing the
bootstrap IP if connecting to upstream failed.
This commit add support for ctrld to run on freebsd, supported platforms
are amd64/arm64/armv6/armv7,386.
Supporting freebsd also requires adding debian and openresolv resolvconf.
Updates #47
After telling service manager to start ctrld, performing self check
status by sending DNS query to ctrld listener. So if ctrld could not
start for any reason, an error message will be reported to user instead
of simply telling service started.
Updates #56
For interface managed by systemd-networkd, systemd-resolved can not
reset DNS. To fix this, attempting to check before the run loop and set
the suitable manager for the system.
Updates #55
For address already in use error when listening, we have a workaround to
spawn a new listener on different port. However, if that case does not
match, we must fatal to notice the error to user.
Currently, ctrld force NetworkManager ignore auto DNS setup from DHCP
per connection. This does not work well, because an interface can be
attached to many connections. So if `ctrld` started with a connection,
then user connect to new one, the DNS configured by ctrld will be
override.
Instead, we can force NetworkManager not to manage DNS by:
- Using dns=none
- Set systemd-resolved=false
So NetworkManager won't attempt to send DNS setup to systemd-resolved,
leaving what ctrld set as-is.
On some Ubuntu systems, we experiment with DNS is not set even though
systemd-resolved log indicates that it set them. To ensure the DNS will
be set, after setting them, double check the current DNS for interface
is actually the value was set, if not, attempting to set again.
While at it, also make sure the DNS is set when ctrld start on Linux.
Currently, when reset DNS, ctrld always find the net.Interface by
interface name. This may produce unexpected error because the interface
table may be cleared at the time ctrld is being stopped.
Instead, we can get the net interface only once, and use that interface
for restoring the DNS before shutting down.
While at it, also making logging message clearer.