If identical queries from IPv4 and IPv6 sources are combined by the
new code added in 15b60ddf93 then replies
can end up being sent via the wrong family of socket. The ->fd
should be per query, not per-question.
In bind-interfaces mode, this could also result in replies being sent
via the wrong socket even when IPv4/IPV6 issues are not in play.
Unlike COPTS=-DHAVE_DNSSEC, allow usage of just sha256 function from
nettle, but keep DNSSEC disabled at build time. Skips use of internal
hash implementation without support for validation built-in.
If we add the EDNS client subnet option, or the client's
MAC address, then the reply we get back may very depending on
that. Since the cache is ignorant of such things, it's not safe to
cache such replies. This patch determines when a dangerous EDNS
option is being added and disables caching.
Note that for much the same reason, we can't combine multiple
queries for the same question when dangerous EDNS options are
being added, and the code now handles that in the same way. This
query combining is required for security against cache poisoning,
so disabling the cache has a security function as well as a
correctness one.
Previously, such queries would all be forwarded
independently. This is, in theory, inefficent but in practise
not a problem, _except_ that is means that an answer for any
of the forwarded queries will be accepted and cached.
An attacker can send a query multiple times, and for each repeat,
another {port, ID} becomes capable of accepting the answer he is
sending in the blind, to random IDs and ports. The chance of a
succesful attack is therefore multiplied by the number of repeats
of the query. The new behaviour detects repeated queries and
merely stores the clients sending repeats so that when the
first query completes, the answer can be sent to all the
clients who asked. Refer: CERT VU#434904.
Use the SHA-256 hash function to verify that DNS answers
received are for the questions originally asked. This replaces
the slightly insecure SHA-1 (when compiled with DNSSEC) or
the very insecure CRC32 (otherwise). Refer: CERT VU#434904.
At any time, dnsmasq will have a set of sockets open, bound to
random ports, on which it sends queries to upstream nameservers.
This patch fixes the existing problem that a reply for ANY in-flight
query would be accepted via ANY open port, which increases the
chances of an attacker flooding answers "in the blind" in an
attempt to poison the DNS cache. CERT VU#434904 refers.
From 606d638918edb0e0ec07fe27eb68d06fb5ebd981 Mon Sep 17 00:00:00 2001
From: Miao Wang <shankerwangmiao@gmail.com>
Date: Fri, 4 Dec 2020 09:59:37 +0800
Subject: [PATCH v2] pxe: support pxe clients with custom vendor-class
According to UEFI[1] and PXE[2] specs, PXE clients are required to have
`PXEClient` identfier in the vendor-class field of DHCP requests, and
PXE servers should also include that identifier in their responses.
However, the firmware of servers from a few vendors[3] are customized to
include a different identifier. This patch adds an option named
`dhcp-pxe-vendor` to provide a list of such identifiers. The identifier
used in responses sent from dnsmasq is identical to that in the coresponding
request.
[1]: https://uefi.org/sites/default/files/resources/UEFI%20Spec%202.8B%20May%202020.pdf
[2]: http://www.pix.net/software/pxeboot/archive/pxespec.pdf
[3]: For instance, TaiShan servers from Huawei, which are Arm64-based,
send `HW-Client` in PXE requests up to now.
Signed-off-by: Miao Wang <shankerwangmiao@gmail.com>
This patch fixes a buffer overflow in TCP requests. Since the read is not
actually being retried, the byte written by the child can be left
in the pipe. When that happens, cache_recv_insert() reads the length of the
name, which is now multiplied by 256 due to the extra 0 byte (8 bit shift)
and results in daemon->namebuff being overflowed.
Namebuff is immediately before the daemon struct in memory so it
ends up corrupting the beginning of the daemon struct.
The initial call to enumerate_interfaces() happens before the
logging subsystem in initialised and the startup banner logged.
It's not intended that syslog be written at this point.
Save listening address into listener. Use it to find existing listeners
before creating new one. If it exist, increase just used counter.
Release only listeners not already used.
Duplicates family in listener.
If interface is recreated with the same address but different index, it
would not change any other parameter.
Test also address family on incoming TCP queries.
Log in debug mode listening on interfaces. They can be dynamically
found, include interface number, since it is checked on TCP connections.
Print also addresses found on them.
We call this, which avoids POLLERR returns from netlink on a loaded system,
if the kernel is new enough to support it. Sadly, qemu-user doesn't support
the socket option, so if it fails despite the kernel being new enough to
support it, we just emit a warning, rather than failing hard.
Hi Simon,
> Add --shared-network config. This enables allocation of addresses
> the DHCP server in subnets where the server (or relay) doesn't
> have an interface on the network in that subnet. Many thanks to
> kamp.de for sponsoring this feature.
Does this paragraph lack a preposition "by" early on the 2nd line, or am
I mis-guessing the purpose?
...enables allocation of addresses *by* the DHCP server...
The manual page also seems to offer room for linguistic improvement
(apparently written by a German, so I see the typical patterns, and also
the misuse of which vs. that.
I am attaching a patch series vs. git to fix several issues in the
manpage and CHANGELOG.
From 35b88d98429e2fe016d9989d220f6faf2b933764 Mon Sep 17 00:00:00 2001
From: Matthias Andree <matthias.andree@gmx.de>
Date: Sun, 5 Apr 2020 11:18:05 +0200
Subject: [PATCH 1/5] man/dnsmasq.8: Properly capitalize DHCP acronym.
A call to get_new_frec() for a DNSSEC query could manage to
free the original frec that we're doing the DNSSEC query to validate.
Bad things then happen.
This requires that the original frec is old, so it doesn't happen
in practice. I found it when running under gdb, and there have been
reports of SEGV associated with large system-clock warps which are
probably the same thing.
Same as for the dbus, allow specifying ubus service name (namespace) on
the command line as an optional argument to --enable-ubus option.
Signed-off-by: Oldřich Jedlička <oldium.pro@gmail.com>
If dnsmasq is not acting as an authoritative nameserver (no second
argument to --auth-server) then it should not appear in the NS RRset.
This leaves simply the list of servers specified in --auth-sec-servers.
When ubus_add_object fails, the ubus_connect object is not freed, so the
connection leaks. Add ubus_destroy to free the connection object.
Signed-off-by: Oldřich Jedlička <oldium.pro@gmail.com>
Error with prefixed address assignment. When it is calculating number of
addresses from prefixlen, it rotates only 32bit int instead of 64b uint.
Only result is assigned to 64b variable.
Two examples:
dhcp-host=[2000::1230:0:0/92],correct-prefix
dhcp-host=[2000::1234:5678:0/92],incorrect-prefix
If prefix length is lower than 96, the result is zero. It means
incorrect-prefix is not refused as it should. Fix is simple, attaching
patch with it. Just rotate 64b int.
There was discussion in the past regarding DHCPv6 NTP server option
which needs special subclassing per RFC5908.
Patch adds support for unicast, multicast IPv6 address and for FQDN string,
preserving possibly used (as suggested earlier) hex value.
Unfortunately it's still not fully free from limitations - only address list or
only fqdn value list is possible, not mixed due current
state option parsing & flagging.
rfc3315.c:1711:28: warning: use of logical '&&' with constant operand [-Wconstant-logical-operand]
if (!(addr_list->flags && ADDRLIST_DECLINED) ||
^ ~~~~~~~~~~~~~~~~~
It's a flag bit so should be bitwise '&' operator
Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
When dhcp-host options can have many IPv6 addresses, we need
to deal with one of them being declined by a client. The other
addresses are still valid.
It seems that this logic never worked, even with only one address, since
the DECLINED flag was never tested.
Route lookup in Linux is bounded by `ip rules` as well
as the contents of specific routing tables. With the
advent of vrf's(l3mdev's) non-default tables are regularly being
used for routing purposes.
dnsmasq listens to all route changes on the box and responds
to each one with an event. This is *expensive* when a full
BGP routing table is placed into the linux kernel, moreso
when dnsmasq is responding to events in tables that it will
never actually need to respond to, since dnsmasq at this
point in time has no concept of vrf's and would need
to be programmed to understand them. Help alleviate this load
by reducing the set of data that dnsmasq pays attention to
when we know there are events that are not useful at this
point in time.
Signed-off-by: Donald Sharp <donaldsharp72@gmail.com>
Errors encountered if building with 'NO_DHCP6' introduced by
commit 137286e9ba
option.c: In function 'dhcp_config_free':
option.c:1040:24: error: 'struct dhcp_config' has no member named 'addr6'; did you mean 'addr'?
for (addr = config->addr6; addr; addr = tmp)
^~~~~
addr
option.c: In function 'one_opt':
option.c:3227:7: error: 'struct dhcp_config' has no member named 'addr6'; did you mean 'addr'?
new->addr6 = NULL;
^~~~~
addr
Wrap new code in ifdef HAVE_DHCP6
Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
Dnsmasq needs to close all the file descriptors it inherits, for security
reasons. This is traditionally done by calling close() on every possible
file descriptor (most of which won't be open.) On big servers where
"every possible file descriptor" is a rather large set, this gets
rather slow, so we use the /proc/<pid>/fd directory to get a list
of the fds which are acually open.
This only works on Linux. On other platforms, and on Linux systems
without a /proc filesystem, we fall back to the old way.
Make the existing "insecure DS received" warning more informative by
reporting the domain name reporting the issue.
This may help identify a problem with a specific domain or server
configuration.
Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
Instead, check only local configured entries are answered without
rdbit set. All cached replies are still denied, but locally configured
names are available with both recursion and without it.
Fixes commit 4139298d28 unintended
behaviour.
When dnsmasq forks a child to handle a TCP connection, that
child inherits the netlink socket that the main process has open.
The child never uses that socket, but there's a chance that when the
main process uses the netlink socket, the answer will go to a child
process which has a copy of the socket. This causes the main process
to block forever awaiting the answer which never comes.
The solution is for the child process to close the netlink socket it
inherits after the fork(). There's a nasty race because the error
decribed above could still occur in the window between the fork()
and the close() syscalls. That's fixed by blocking the parent awaiting
a single byte sent though the pipe the two processes share. This byte
is sent by the child after calling close() on the netlink socket.
Thanks to Alin Năstac for spotting this.
When a request matching the clid or mac address is
recieved the server will iterate over all candidate
addresses until it find's one that is not already
leased to a different clid/iaid and advertise
this address.
Using multiple reservations for a single host makes it
possible to maintain a static leases only configuration
which support network booting systems with UEFI firmware
that request a new address (a new SOLICIT with a new IA_NA
option using a new IAID) for different boot modes, for
instance 'PXE over IPv6', and 'HTTP-Boot over IPv6'. Open
Virtual Machine Firmware (OVMF) and most UEFI firmware
build on the EDK2 code base exhibit this behaviour.
The previous code here, which started fast-RA whenever that local
address associated with a DHCP context changed, is very vulnerable
to flapping due to dynamically created addresses in the same net.
Simplify so that if a context which has never found an interface now
finds one, that gets advertised, but not for other changes. That satisfies
the original intention that prefixes not in place when dnsmasq starts
should be recognised.
Also totally ignore all interfaces where we are configured not to do DHCP,
to preclude flapping of they have prefixes in common with interfaces
where we do DHCP.
Fail on overlarge files (block numbers are limited to 16 bits)
Honour tftp-max setting in single port mode.
Tweak timeouts, and fix logic which suppresses errors if the
last ACK is missing.
Hello,
My home network has a DNS search domain of home.arpa and my machine's dnsmasq
instance is configured with:
server=/home.arpa/192.168.0.1
server=//192.168.0.1
stop-dns-rebind
rebind-domain-ok=home.arpa
rebind-domain-ok=// # Match unqualified domains
Querying my router's FQDN works as expected:
dnsmasq: query[A] gateway.home.arpa from 127.0.0.1
dnsmasq: forwarded gateway.home.arpa to 192.168.0.1
dnsmasq: reply gateway.home.arpa is 192.168.0.1
But using an unqualified domain name does not:
dnsmasq: query[A] gateway from 127.0.0.1
dnsmasq: forwarded gateway to 192.168.0.1
dnsmasq: possible DNS-rebind attack detected: gateway
The attached patch addresses this issue by checking for SERV_NO_REBIND when
handling dotless domains.
>From 0460b07108b009cff06e29eac54910ec2e7fafce Mon Sep 17 00:00:00 2001
From: guns <self@sungpae.com>
Date: Mon, 30 Dec 2019 16:34:23 -0600
Subject: [PATCH] Check for SERV_NO_REBIND on unqualified domains
Calling lease_update_file() _can_ result in a call to periodic_ra()
Since both the DHCPv6 and RA subsystems use the same packet buffer
this can overwrite the DHCPv6 packet. To avoid this we ensure the
DHCPv6 packet has been sent before calling lease_update_file().
Order dnsmasq.service before network.target and after network-online.target & nss-lookup.target. Additionally pull in nss-lookup.target.
This matches the behaviour of systemd-resolved and Unbound.
Signed-off-by: nl6720 <nl6720@gmail.com>
Cope with cached and configured CNAMES for all record types we
support, including local-config but not cached types such as TXT.
Also, if we have a locally configured CNAME but no target for the
requested type, don't forward the query.
The idea of this option was already discussed years ago on the mailing
list:
https://dnsmasq-discuss.thekelleys.org.narkive.com/ZoFQNaGo/always-ignore-client-identifier#post4
In our production environnement, we discovered that some devices are
using 'client identifier' not unique at all, resulting on IP addresses
conflicts between several devices (we saw up to four devices using same
IP address).
The root cause is probably a buggy operating system/configuration of
decices, but this patch add a configuration workaround on server side
when fixing clients is impossible.
Signed-off-by: Charles Daymand <charles.daymand@wifirst.fr>
Signed-off-by: Florent Fourcot <florent.fourcot@wifirst.fr>
Some REFUSED answers to DNSSEC-originated queries would
bypass the DNSSEC code entirely, and be returned as answers
to the original query. In the process, they'd mess up datastructures
so that a retry of the original query would crash dnsmasq.
If no IPv4 address is present on given interface, the tool would not
send any request. It would not report any error at the same time. Report
error if request send failed.
Signed-off-by: Petr Mensik <pemensik@redhat.com>
Currently, dhcp_release will only send a 'fake' release
when the address given is in the same subnet as an IP
on the interface that was given.
This doesn't work in an environment where dnsmasq is
managing leases for remote subnets via a DHCP relay, as
running dhcp_release locally will just cause it to
silently exit without doing anything, leaving the lease
in the database.
Change it to use the default IP on the interface, as the
dnsmasq source code at src/dhcp.c does, if no matching subnet
IP is found, as a fall-back. This fixes an issue we are
seeing in certain Openstack deployments where we are using
dnsmasq to provision baremetal systems in a datacenter.
While using Dbus might have seemed like an obvious solution,
because of our extensive use of network namespaces (which
Dbus doesn't support), this seemed like a better solution
than creating system.d policy files for each dnsmasq we
might spawn and using --enable-dbus=$id in order to isolate
messages to specific dnsmasq instances.
Signed-off-by: Brian Haley <haleyb.dev@gmail.com>
In a reply proving that a DS doesn't exist, it doesn't matter if RRs
in the auth section _other_ than NSEC/NSEC3 are not signed. We can't
set the AD flag when returning the query, but it still proves
that the DS doesn't exist for internal use.
As one of the RRs which may not be signed is the SOA record, use the
TTL of the NSEC record to cache the negative result, not one
derived from the SOA.
Thanks to Tore Anderson for spotting and diagnosing the bug.
If the cache size is very large, the malloc() call will overflow
on 32 bit platforms and dnsmasq will crash. Limit to an order of
magnitude less.
Thanks to Lili Xu for spotting this.
- aligned the handling of UBus connections with the DBus code as it
makes it a bit easier to comprehend;
- added logging to the various UBus calls to aid debugging from an
enduser point of view, but be careful to not flood the logs;
- show the (lack of) support for UBus in the configuration string.
msg_controllen should be set using CMSG_SPACE() to account for padding.
RFC3542 provides more details:
While sending an application may or may not include padding at the end
of last ancillary data in msg_controllen and implementations must
accept both as valid.
At least OpenBSD rejects control messages if msg_controllen doesn't
account for padding, so use CMSG_SPACE() for maximal portability. This
is consistent with the example provided in the Linux cmsg(3) manpage.
Dear Simon,
the attached patch removes three redundant prototypes from dnsmasq.h. There is no functional change.
Best regards,
Dominik
From c0b2ccfd20c4eec9d09468fdfe9b4ca8a8f8591e Mon Sep 17 00:00:00 2001
From: DL6ER <dl6er@dl6er.de>
Date: Sun, 10 Mar 2019 19:34:07 +0100
Subject: [PATCH] Remove redundant prototypes from dnsmasq.h
Signed-off-by: DL6ER <dl6er@dl6er.de>
We detected a performance issue on a dnsmasq running many dhcp sessions
(more than 10 000). At the end of the day, the server was only releasing
old DHCP leases but was consuming a lot of CPU.
It looks like curent dhcp pruning:
1) it's pruning old sessions (iterate on all current leases). It's
important to note that it's only pruning session expired since more
than one second
2) it's looking for next lease to expire (iterate on all current leases
again)
3) it launchs an alarm to catch next expiration found in step 2). This
value can be zero for leases just expired (but not pruned).
So, for a second, dnsmasq could fall in a "prune loop" by doing:
* Not pruning anything, since difftime() is not > 0
* Run alarm again with zero as argument
On a server with very large number of leases and releasing often
sessions, that can waste a very big CPU time.
Signed-off-by: Florent Fourcot <florent.fourcot@wifirst.fr>
There's no reason to stop reading the existing lease file
when dnsmasq is started and an invalid entry is found, it
can just be ignored. This was fallout from an Openstack
bug where the file was being written incorrectly with []
around IPv6 addresses.
It is possible for a config entry to have one address family specified by a
dhcp-host directive and the other added from /etc/hosts. This is especially
common on OpenWrt because it uses odhcpd for DHCPv6 and IPv6 leases are
imported into dnsmasq via a hosts file.
To handle this case there need to be separate *_HOSTS flags for IPv4 and IPv6.
Otherwise when the hosts file is reloaded it will clear the CONFIG_ADDR(6) flag
which was set by the dhcp-host directive.
This moves the class argument to cache-insert into an argument,
rather then overloading a union in the address argument. Note that
tha class is NOT stored in the cache other than for DS/DNSKEY entries,
so must always be C_IN except for these. The data-extraction code
ensures this as it only attempts to cache C_IN class records.
Avoid offering the same address after a recieving a DECLINE message
to stop an infinite protocol loop. This has long been done in
default address allocation mode: this adds similar behaviour
when allocaing addresses consecutively.
Hi Simon,
master has a build error when building without HAVE_DHCPv6
option.c: In function 'dhcp_context_free':
option.c:1042:15: error: 'struct dhcp_context' has no member named 'template_interface'
free(ctx->template_interface);
Sadly, need to put in a little conditional compilation ifdef'erey
Simplest patch in the world attached
Cheers,
Kevin D-B
012C ACB2 28C6 C53E 9775 9123 B3A2 389B 9DE2 334A
From 061eb8599636bb360e0b7fa5986935b86db39497 Mon Sep 17 00:00:00 2001
From: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
Date: Mon, 10 Dec 2018 10:07:33 +0000
Subject: [PATCH] option: fix non DHCPv6 build error
option.c: In function 'dhcp_context_free':
option.c:1042:15: error: 'struct dhcp_context' has no member named 'template_interface'
free(ctx->template_interface);
^~
Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
Hi Simon,
Another one fallen out of the openwrt tree shake :-)
ipv6 ipset addresses weren’t being set correctly. patch attached
Cheers,
Kevin D-B
012C ACB2 28C6 C53E 9775 9123 B3A2 389B 9DE2 334A
From b50fc0491e374186f982b019f293379955afd203 Mon Sep 17 00:00:00 2001
From: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
Date: Wed, 12 Dec 2018 11:35:12 +0000
Subject: [PATCH] ipset fix ternary order swap
ee87504 Remove ability to compile without IPv6 support introduced a
ternary operator for ip address size. Unfortunately the true/false
order was incorrect which meant ipv6 ipset addresses were added
incorrectly.
Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
The queries will not be forwarded to a server for a domain, unless
there's a trust anchor provided for that domain. This allows, especially,
suitable proof of non-existance for DS records to come from
the parent domain for domains which are not signed.
This time I have a little bit more controversal patches. But I think
still useful. They fixes memory leaks that might occur in some cases.
Most dnsmasq errors is fatal, so it does not matter. But some are not.
Some parts are reloaded on SIGHUP signal, so it might leak more than once.
Some example when it changes the failures. Use dhcp-options file with
this content:
tag:error,vendor:redhat
option:ntp-server,1.2.3.4.5
option6:ntp-server,[:::]
Is not fatal and dnsmasq will start. On each reload command, it would
leak some memory. I validated it using valgrind --leak-check=full
dnsmasq -d. This patch fixes it. It introduces something that might be
considered constructor and destructor of selected structures.
In an era where everything has an MMU, this looks like
an anachronism, and it adds to (Ok, multiplies!) the
combinatorial explosion of compile-time options.
The above is intended to increase robustness, but actually does the
opposite. The problem is that by ignoring SERVFAIL messages and hoping
for a better answer from another of the servers we've forwarded to,
we become vulnerable in the case that one or more of the configured
servers is down or not responding.
Consider the case that a domain is indeed BOGUS, and we've send the
query to n servers. With 68f6312d4b
we ignore the first n-1 SERVFAIL replies, and only return the
final n'th answer to the client. Now, if one of the servers we are
forwarding to is down, then we won't get all n replies, and the
client will never get an answer! This is a far more likely scenario
than a temporary SERVFAIL from only one of a set of notionally identical
servers, so, on the ground of robustness, we have to believe
any SERVFAIL answers we get, and return them to the client.
The client could be using the same recursive servers we are,
so it should, in theory, retry on SERVFAIL anyway.
If arg2 of pkg-wrapper is "--copy", then arg1 is NOT the name of
the package manager (--copy doesn't invoke it) it's a secondary
config string that inhibts the copy if found. This patch allows that
to be the empty string, for unconditional copy, and modifies the
ubus linker config to use it. It worked by coincidence before, because
there was no config string called "pkg-config".
Make options bits derived from size and count. Use size of option bits
and last supported bit in computation. No new change would be required
when new options are added. Just change OPT_LAST constant.
Chaos .bind and .server (RFC4892) zones are local, therefore
don't forward queries upstream to avoid mixing with supported
locally and false replies with NO_ID enabled.
This was the source of a large number of #ifdefs, originally
included for use with old embedded libc versions. I'm
sure no-one wants or needs IPv6-free code these days, so this
is a move towards more maintainable code.
For ease of implementaion, dnsmasq has always forked a new process to
handle each incoming TCP connection. A side-effect of this is that any
DNS queries answered from TCP connections are not cached: when TCP
connections were rare, this was not a problem. With the coming of
DNSSEC, it's now the case that some DNSSEC queries have answers which
spill to TCP, and if, for instance, this applies to the keys for the
root then those never get cached, and performance is very bad. This
fix passes cache entries back from the TCP child process to the main
server process, and fixes the problem.
The code which conirms possible SLAAC addresses associated with
hosts known from DHCPv4 addresses keeps trying at longer and longer
intervals essentially forever, EXCEPT if sending an ICMP ping results
in a HOSTUNREACH error, which terminates the process immediately.
It turns out that this is too drastic. Routing changes associated
with addressing changes can cause temporary HOSTUNREACH problems,
even when an address has not gone forever. Therefore continue
trying in the face of HOSTUNREACH for the first part of the
process. HOSTUNREACH errors will still terminate the process
after it reaches the slow tail of retries.
Thanks to Andrey Vakhitov for help diagnosing this.
But make auth-server required when any auth-zones are defined.
The "glue record" field in auth-server is needed to synthesise
SOA and NS records in auth zones, so the --auth-server has to
be specified. If makes sense, however to define one or more
auth-zones that appear within the normal recursive DNS service
without actually acting as an authoritative DNS server on
any interface. Hence making the interface field optional.
These normally have enough space for a name of up to SMALLDNAME characters.
When used to hold /etc/hosts entries, they are allocated with just enough
bytes for the name held. When used to hold other configured stuff, (CNAMES
DS records. DHCP names etc), the name is replaced by a pointer to a string
held elsewhere, and F_NAMEP set. Hence only enough space to hold a char *
is needed, rather than SMALLDNAME bytes.
Many thanks to Kristian Evensen for finding and diagnosing this.
We can't copy the whole of a crec structure in make_non_terminals, since
crec structures allocated to represent /etc/hosts entries are allocated with
just enough space for the actual name they contain, not the full
SMALLDNAME bytes declared in struct crec. Using structure copy therefore
copies beyond the end of the allocated source and, just occaisionally,
into unmapped memory, resulting in a SEGV.
Since the crecs we're making here always have F_NAMEP set, we're not
interested in copying the name field from the source anyway, we use the
namep part of the union and set it to point some way into the name
of the source crec to get the super-domain that we're representing.
The fix is therefore to copy the relevant fields of the crec, rather
than copying the whole and overwriting.
Change anti cache-snooping behaviour with queries with the
recursion-desired bit unset. Instead to returning SERVFAIL, we
now always forward, and never answer from the cache. This
allows "dig +trace" command to work.
When a record is defined locally, eg an A record for one.two.example then
we already know that if we forward, eg an AAAA query for one.two.example,
and get back NXDOMAIN, then we need to alter that to NODATA. This is handled
by check_for_local_domain(). But, if we forward two.example, because
one.two.example exists, then the answer to two.example should also be
a NODATA.
For most local records this is easy, just to substring matching.
for A, AAAA and CNAME records that are in the cache, it's more difficult.
The cache has no efficient way to find such records. The fix is to
insert empty (none of F_IPV4, F_IPV6 F_CNAME set) records for each
non-terminal.
The same considerations apply in auth mode, and the same basic mechanism
is used there too.
The option was already described in the original manual page but was not
replicated in the french translation.
Reviewed-By: Nicolas Cavallari <nicolas.cavallari@green-communications.fr>
The use of "peut-être" should be spelled "peut être" (without the
hyphen) unless it can be replaced by "sans doute".
It is roughly the same difference between "maybe" and "may be".
As for "doit-être", it should always be spelled "doit être".
Reviewed-By: Nicolas Cavallari <nicolas.cavallari@green-communications.fr>
Various typos were present along with spelling mistakes and grammar
errors. Some sentences were missing a few words to be easily
understandable.
Many of them probably remain though.
Reviewed-By: Nicolas Cavallari <nicolas.cavallari@green-communications.fr>
When inserting new cache records, we first delete existing records
of the same name/type, to maintain consistency. This has the side effect
of deleting any CNAMES which have the records as target. So
cname1.example CNAME record.example
cname2.example CNAME record.example
looking up cname2.example will push it into the cache, and also
push record.example. Doing that deletes any cache of cname1.example.
This changeset avoids that problem by making sure that when
deleting record.example, and re-insterting it (with the same name -important),
it uses the same struct crec, with the same uid. This preserves the existing cnames.
Dnsmasq does pass on the do-bit, and return DNSSEC RRs, irrespective
of of having DNSSEC validation compiled in or enabled.
The thing to understand here is that the cache does not store all the
DNSSEC RRs, and dnsmasq doesn't have the (very complex) logic required
to determine the set of DNSSEC RRs required in an answer. Therefore if
the client wants the DNSSEC RRs, the query can not be answered from
the cache. When DNSSEC validation is enabled, any query with the
do-bit set is never answered from the cache, unless the domain is
known not to be signed: the query is always forwarded. This ensures
that the DNSEC RRs are included.
The same thing should be true when DNSSEC validation is not enabled,
but there's a bug in the logic.
line 1666 of src/rfc1035.c looks like this
if ((crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) || !do_bit || !(crecp->flags & F_DNSSECOK))
{ ...answer from cache ... }
So local stuff (hosts, DHCP, ) get answered. If the do_bit is not set
then the query is answered, and if the domain is known not to be
signed, the query is answered.
Unfortunately, if DNSSEC validation is not turned on then the
F_DNSSECOK bit is not valid, and it's always zero, so the question
always gets answered from the cache, even when the do-bit is set.
This code should look like that at line 1468, dealing with PTR queries
if ((crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) ||
!do_bit ||
(option_bool(OPT_DNSSEC_VALID) && !(crecp->flags & F_DNSSECOK)))
where the F_DNSSECOK bit is only used when validation is enabled.
I noticed that dnsmasq often wasn't sending any unsolicited RAs for me.
This turned out to happen when the interface (a bridge interface) wasn't
created yet at the time dnsmasq started. When dnsmasq is started after
the interface is created, it sends RAs as expected. I assume this also
extends to other types of virtual interfaces that are created after
dnsmasq starts.
Digging into the source, it seems to be caused by a missing call to
ra_start_unsolicited for non-template contexts in construct_worker from
src/dhcp6.c. The attached patch adds that call, but only if the
interface index or address changed to prevent doing fast RAs for no reason.
I tested it on my own server and it appears to work as expected. When
the interface is created and configured, dnsmasq does fast RAs for a
while and then settles into slow RAs.
If we're talking to upstream servers from a fixed port, specified by query-port
we create the fds to do this once, before dropping root, so that ports <1024 can be used.
But we call check_servers() before reading /etc/resolv.conf, so if the only servers
are in resolv.conf, at that point there will be no servers, and the fds get garbage
collected away, only to be recreated (but without root) after we read /etc/resolv.conf
Make pre-allocated server fds immortal, to avoid this problem.
If query-port is set, we create sockets bound to the wildcard address and the query port for
IPv4 and IPv6, but the IPv6 one fails, because is covers IPv4 as well, and an IPv4 socket
already exists (it gets created first). Set V6ONLY to avoid this.
Install-common section was creating superfluous '-d' directory in build
location.
Split the directory creation into individual install commands to cope
with cross platform differences of interpreting subsequent '-d'
arguments. e.g. GNU appears to be fine. Apple creates the stray
directory.
Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
I got reported bug in Fedora [1], that cname is broken in new releases.
At first I though this was false report, but there is still new
regression in cname handling.
Before, it accepted alias with trailing dot. Not it would accept only
target, but not alias.
cname=alias.,target
is no longer valid. The issue is it will count size to skip after
canonicalize. If that ignores trailing dot, next name would be "". And
that is invalid and refused, dnsmasq refuses to start.
I also think that any whitespace like tab should be possible after
comma. So this fixes also 30858e3b9b.
The way of accessing the list of available hashes on nettle was
vulnerable to breaking if the version of libnettle in use was
different to the version dnsmasq was compiled against.
Change to a new system if libnettle >= 3.4 is in use.
Older versions if nettle are still OK, once 3.4 is reached,
the ABi problem is fixed. Thanks to Petr Menšík for clues on this.
Use strlen to determine the length of the filename returned by
inotify, as in->len refers to the length of the buffer containing
the name, not the length of the name itself.
http://lists.thekelleys.org.uk/pipermail/dnsmasq-discuss/2018q1/011950.html
Signed-off-by: Andy Hawkins <andy@gently.org.uk>
Patch further modified by simon@thekelleys.org to avoid
out-of-bounds array access with an empty string, call strlen once,
and reverse order of filename verifcation and resolv-file test.
It's OK for NSEC records to be expanded from wildcards,
but in that case, the proof of non-existence is only valid
starting at the wildcard name, *.<domain> NOT the name expanded
from the wildcard. Without this check it's possible for an
attacker to craft an NSEC which wrongly proves non-existence
in a domain which includes a wildcard for NSEC.
RFC 4034 says:
[RFC2181] specifies that an RRset is not allowed to contain duplicate
records (multiple RRs with the same owner name, class, type, and
RDATA). Therefore, if an implementation detects duplicate RRs when
putting the RRset in canonical form, it MUST treat this as a protocol
error. If the implementation chooses to handle this protocol error
in the spirit of the robustness principle (being liberal in what it
accepts), it MUST remove all but one of the duplicate RR(s) for the
purposes of calculating the canonical form of the RRset.
We chose to handle this robustly, having found at least one recursive
server in the wild which returns duplicate NSEC records in the AUTHORITY
section of an answer generated from a wildcard record. sort_rrset() is
therefore modified to delete duplicate RRs which are detected almost
for free during the bubble-sort process.
Thanks to Toralf Förster for helping to diagnose this problem.
If all configured dns servers return refused in
response to a query; dnsmasq will end up in an infinite loop
retransmitting the dns query resulting into high CPU load.
Problem is caused by the dns refuse retransmission logic which does
not check for the end of a dns server list iteration in strict mode.
Having one configured dns server returning a refused reply easily
triggers this problem in strict order mode. This was introduced in
9396752c11
Thanks to Hans Dedecker <dedeckeh@gmail.com> for spotting this
and the initial patch.
Some of our Openstack users run quite large number of dnsmasq instances
on single host. They started hitting default limit of inotify socket
number on single system after upgrade to more recent version. System
defaults of sysctl fs.inotify.max_user_instances is 128. They reached
limit of 116 dnsmasq instances, then more instances failed to start.
I was surprised they have any use case for such high number of
instances. They use one dnsmasq for one virtual network.
I found simple way to avoid hitting low system limit. They do not use
resolv.conf for name server configuration or any dhcp hosts or options
directory. Created inotify socket is never used in that case. Simple
patch attached.
I know we can raise inotify system limit. I think better is to not waste
resources that are left unused.
The current logic is naive in the case that there is more than
one RRset in an answer (Typically, when a non-CNAME query is answered
by one or more CNAME RRs, and then then an answer RRset.)
If all the RRsets validate, then they are cached and marked as validated,
but if any RRset doesn't validate, then the AD flag is not set (good) and
ALL the RRsets are cached marked as not validated.
This breaks when, eg, the answer contains a validated CNAME, pointing
to a non-validated answer. A subsequent query for the CNAME without do
will get an answer with the AD flag wrongly reset, and worse, the same
query with do will get a cached answer without RRSIGS, rather than
being forwarded.
The code now records the validation of individual RRsets and that
is used to correctly set the "validated" bits in the cache entries.
The logic to determine is an EDNS0 header was added was wrong. It compared
the packet length before and after the operations on the EDNS0 header,
but these can include adding options to an existing EDNS0 header. So
a query may have an existing EDNS0 header, which is extended, and logic
thinks that it had a header added de-novo.
Replace this with a simpler system. Check if the packet has an EDSN0 header,
do the updates/additions, and then check again. If it didn't have one
initially, but it has one laterly, that's the correct condition
to strip the header from a reply, and to assume that the client
cannot handle packets larger than 512 bytes.
dnsmasq allows to specify a interface for each name server passed with
the -S option or pushed through D-Bus; when an interface is set,
queries to the server will be forced via that interface.
Currently dnsmasq uses SO_BINDTODEVICE to enforce that traffic goes
through the given interface; SO_BINDTODEVICE also guarantees that any
response coming from other interfaces is ignored.
This can cause problems in some scenarios: consider the case where
eth0 and eth1 are in the same subnet and eth0 has a name server ns0
associated. There is no guarantee that the response to a query sent
via eth0 to ns0 will be received on eth0 because the local router may
have in the ARP table the MAC address of eth1 for the IP of eth0. This
can happen because Linux sends ARP responses for all the IPs of the
machine through all interfaces. The response packet on the wrong
interface will be dropped because of SO_BINDTODEVICE and the
resolution will fail.
To avoid this situation, dnsmasq should only restrict queries, but not
responses, to the given interface. A way to do this on Linux is with
the IP_UNICAST_IF and IPV6_UNICAST_IF socket options which were added
in kernel 3.4 and, respectively, glibc versions 2.16 and 2.26.
Reported-by: Hector Martin <marcan@marcan.st>
Signed-off-by: Beniamino Galvani <bgalvani@redhat.com>
Further fix to 0549c73b7e
Handles case when RR name is not a pointer to the question,
only occurs for some auth-mode replies, therefore not
detected by fuzzing (?)
Fix out-of-memory Dos vulnerability. An attacker which can
send malicious DNS queries to dnsmasq can trigger memory
allocations in the add_pseudoheader function
The allocated memory is never freed which leads to a DoS
through memory exhaustion. dnsmasq is vulnerable only
if one of the following option is specified:
--add-mac, --add-cpe-id or --add-subnet.
Fix DoS in DNS. Invalid boundary checks in the
add_pseudoheader function allows a memcpy call with negative
size An attacker which can send malicious DNS queries
to dnsmasq can trigger a DoS remotely.
dnsmasq is vulnerable only if one of the following option is
specified: --add-mac, --add-cpe-id or --add-subnet.
Fix information leak in DHCPv6. A crafted DHCPv6 packet can
cause dnsmasq to forward memory from outside the packet
buffer to a DHCPv6 server when acting as a relay.
Fix heap overflow in IPv6 router advertisement code.
This is a potentially serious security hole, as a
crafted RA request can overflow a buffer and crash or
control dnsmasq. Attacker must be on the local network.
Fix heap overflow in DNS code. This is a potentially serious
security hole. It allows an attacker who can make DNS
requests to dnsmasq, and who controls the contents of
a domain, which is thereby queried, to overflow
(by 2 bytes) a heap buffer and either crash, or
even take control of, dnsmasq.
libidn2 strips underscores from international domain names
when encoding them. Indeed, it strips underscores even if
no encoding is necessary, which breaks SRV records.
Don't submit domain names to IDN encoding if they contain
one or more underscores to fix this.
If a DNS server replies REFUSED for a given DNS query in strict order mode
no failover to the next DNS server is triggered as the failover logic only
covers non strict mode.
As a result the client will be returned the REFUSED reply without first
falling back to the secondary DNS server(s).
Make failover support work as well for strict mode config in case REFUSED is
replied by deleting the strict order check and rely only on forwardall being
equal to 0 which is the case in non strict mode when a single server has been
contacted or when strict order mode has been configured.
Commit f77700aa, which fixes a compiler warning, also breaks the
behaviour of prepending ".<layer>" to basenames in --pxe-service: in
situations where the basename contains a ".", the ".<layer>" suffix is
erroneously added, and in situations where the basename doesn't contain
a ".", the ".<layer>" suffix is erroneously omitted.
A patch against the git HEAD is attached that inverts this logic and
restores the expected behaviour of --pxe-service.
Remove historic automatic inclusion of IDN support when
building internationalisation support. This doesn't
fit now there is a choice of IDN libraries. Be sure
to include either -DHAVE_IDN or _DHAVE_LIBIDN2 for
IDN support
This was causing confusion: DNSSEC queries would be sent to
servers for domains that don't do DNSSEC, but because of that status
the answers would be treated as answers to ordinary queries,
sometimes resulting in a crash.
This reverts commit 88a77a78ad.
A least one client has been found which breaks with this change. Since
the use-case is not clear, I'm reverting the change, at least for now.
Dnsmasq's startup script seems to assume users always want to use
dnsmasq as local DNS resolver, and tells resolvconf to put
"nameserver 127.0.0.1" in /etc/resolv.conf
The problem with this is that if users just want to use dnsmasq
as DHCP server, and put port=0 in /etc/dnsmasq.conf to disable
the DNS functionality, they end up with broken name resolving.
Put a basic check in the startup script that skips resolvconf
configuration if a line starting with port=0 is in /etc/dnsmasq.conf
This doesn't cover all cases (e.g. configuration could also be in
different file in /etc/dnsmasq.d), but is better than current
situation.
Adds option to delay replying to DHCP packets by one or more seconds.
This provides a workaround for a PXE boot firmware implementation
that has a bug causing it to fail if it receives a (proxy) DHCP
reply instantly.
On Linux it looks up the exact receive time of the UDP packet with
the SIOCGSTAMP ioctl to prevent multiple delays if multiple packets
come in around the same time.
It is currently only possible to let the TFTP server serve a different
folder depending on the client's IP address.
However it isn't always possible to predict what the client's
IP address will be, especially in situations in which we are not
responsible for handing them out (e.g. proxy dhcp setups).
Extend the current --tftp-unique-root parameter to support having a
separate folder per MAC address instead.
The current --server syntax allows for binding to interface or
address. However, in some (admittedly special) cases it is useful to
be able to specify both. This commit introduces the following syntax
to support binding to both interface and address:
--server X.X.X.X@IP@interface#port
Based on my tests, the syntax is backwards compatible with the current
@IP/interface#port. The code will fail if two interface names are given.
v1->v2:
* Add man page description of the extended server syntax (thanks Simon Kelley)
Signed-off-by: Kristian Evensen <kristian.evensen@gmail.com>
The man page says that we don't do DNSSEC on forwarded domains, but if
you turn on dnssec_check_signatures this turns out to be untrue,
because we try to build up a DS chain to them. Since forwarded domains
are usually used for split DNS to hidden domains, they're unlikely to
verify to the DNS root anyway, so the way to do DNSSEC for them (as the
manual says) is to provide a trust anchor for each forwarder.
The problem I've run into is a split DNS setup where I want DNSSEC to
work mostly, but one of the forwarding domains doesn't have an internal
DNSSEC capable resolver. Without this patch the entire domain goes
unresolvable because the DS record query to the internal resolver
returns a failure which is interpreted as the domain being BOGUS.
The fix is not to do the DS record chase for forwarded domains.
The rev-server directive only handles the following CIDR prefixes
properly: /8, /16, /24, /32.
Any other value was silently converted to /16 which could result in
unexpected behaviour.
This patch rejects any other value instead of making a silent
conversion.
[ excerpt from the man page ]
The rev-server directive provides a syntactic sugar to make specifying
address-to-name queries easier. For example
--rev-server=1.2.3.0/24,192.168.0.1 is exactly equivalent to
--server=/3.2.1.in-addr.arpa/192.168.0.1
It is not mentioned in the man page but the only prefixes that the
directive properly handles when dealing with IPv4 are /8, /16 and /24.
Specifying anything else as the same effect as specifying /16.
It is not a big deal for subnets on non-octet boundaries since they
cannot be represented using a single in-addr.arpa address. However, it
is unconvenient for /32 prefix while the analogous server directive
behaves as expected. E.g. the following server directive work
as expected:
server=/42.10.168.192.in-addr.arpa/1.2.3.4
but the following does not:
rev-server=192.168.10.42/32,1.2.3.4
and, in practice, the later behaves the same as:
server=/168.192.in-addr.arpa/1.2.3.4
This strange behaviour is fixed by accepting /32 CIDR prefixes as a
valid value. Any other value will still be considered the same as /16.
By default 30 first servers are listed individually to system log, and
then a count of the remaining items. With e.g. a NXDOMAIN based adblock
service, dnsmasq lists 30 unnecessary ad sites every time when dnsmasq
evaluates the list. But the actual nameservers in use are evaluated last
and are not displayed as they get included in the "remaining items" total.
Handle the "local addresses only" separately and list only a few of them.
Remove the "local addresses only" from the general count.
This effectively reverts most of 51967f9807 ("SERVFAIL is an expected
error return, don't try all servers.") and 4ace25c5d6 ("Treat REFUSED (not
SERVFAIL) as an unsuccessful upstream response").
With the current behaviour, as soon as dnsmasq receives a SERVFAIL from an
upstream server, it stops trying to resolve the query and simply returns
SERVFAIL to the client. With this commit, dnsmasq will instead try to
query other upstream servers upon receiving a SERVFAIL response.
According to RFC 1034 and 1035, the semantic of SERVFAIL is that of a
temporary error condition. Recursive resolvers are expected to encounter
network or resources issues from time to time, and will respond with
SERVFAIL in this case. Similarly, if a validating DNSSEC resolver [RFC
4033] encounters issues when checking signatures (unknown signing
algorithm, missing signatures, expired signatures because of a wrong
system clock, etc), it will respond with SERVFAIL.
Note that all those behaviours are entirely different from a negative
response, which would provide a definite indication that the requested
name does not exist. In our case, if an upstream server responds with
SERVFAIL, another upstream server may well provide a positive answer for
the same query.
Thus, this commit will increase robustness whenever some upstream servers
encounter temporary issues or are misconfigured.
Quoting RFC 1034, Section 4.3.1. "Queries and responses":
If recursive service is requested and available, the recursive response
to a query will be one of the following:
- The answer to the query, possibly preface by one or more CNAME
RRs that specify aliases encountered on the way to an answer.
- A name error indicating that the name does not exist. This
may include CNAME RRs that indicate that the original query
name was an alias for a name which does not exist.
- A temporary error indication.
Here is Section 5.2.3. of RFC 1034, "Temporary failures":
In a less than perfect world, all resolvers will occasionally be unable
to resolve a particular request. This condition can be caused by a
resolver which becomes separated from the rest of the network due to a
link failure or gateway problem, or less often by coincident failure or
unavailability of all servers for a particular domain.
And finally, RFC 1035 specifies RRCODE 2 for this usage, which is now more
widely known as SERVFAIL (RFC 1035, Section 4.1.1. "Header section format"):
RCODE Response code - this 4 bit field is set as part of
responses. The values have the following
interpretation:
(...)
2 Server failure - The name server was
unable to process this query due to a
problem with the name server.
For the DNSSEC-related usage of SERVFAIL, here is RFC 4033
Section 5. "Scope of the DNSSEC Document Set and Last Hop Issues":
A validating resolver can determine the following 4 states:
(...)
Insecure: The validating resolver has a trust anchor, a chain of
trust, and, at some delegation point, signed proof of the
non-existence of a DS record. This indicates that subsequent
branches in the tree are provably insecure. A validating resolver
may have a local policy to mark parts of the domain space as
insecure.
Bogus: The validating resolver has a trust anchor and a secure
delegation indicating that subsidiary data is signed, but the
response fails to validate for some reason: missing signatures,
expired signatures, signatures with unsupported algorithms, data
missing that the relevant NSEC RR says should be present, and so
forth.
(...)
This specification only defines how security-aware name servers can
signal non-validating stub resolvers that data was found to be bogus
(using RCODE=2, "Server Failure"; see [RFC4035]).
Notice the difference between a definite negative answer ("Insecure"
state), and an indefinite error condition ("Bogus" state). The second
type of error may be specific to a recursive resolver, for instance
because its system clock has been incorrectly set, or because it does not
implement newer cryptographic primitives. Another recursive resolver may
succeed for the same query.
There are other similar situations in which the specified behaviour is
similar to the one implemented by this commit.
For instance, RFC 2136 specifies the behaviour of a "requestor" that wants
to update a zone using the DNS UPDATE mechanism. The requestor tries to
contact all authoritative name servers for the zone, with the following
behaviour specified in RFC 2136, Section 4:
4.6. If a response is received whose RCODE is SERVFAIL or NOTIMP, or
if no response is received within an implementation dependent timeout
period, or if an ICMP error is received indicating that the server's
port is unreachable, then the requestor will delete the unusable
server from its internal name server list and try the next one,
repeating until the name server list is empty. If the requestor runs
out of servers to try, an appropriate error will be returned to the
requestor's caller.
Some consider it good practice to obscure software version numbers to
clients. Compiling with -DNO_ID removes the *.bind info structure.
This includes: version, author, copyright, cachesize, cache insertions,
evictions, misses & hits, auth & servers.
Manual page: clarify that the --address and --ipset options take one or
more domains rather than just two. Clarify that --ipset puts addresses
in all ipsets, it is not a 1:1 mapping from addresses.
Also increase the width for options output in --help, some options were
truncated leading to confusing output. Almost all options and
descriptions are now within the 120 colums limit.
The check that there's enough space to store the DHCP agent-id
at the end of the packet could succeed when it should fail
if the END option is in either of the oprion-overload areas.
That could overwrite legit options in the request and cause
bad behaviour. It's highly unlikely that any sane DHCP client
would trigger this bug, and it's never been seen, but this
fixes the problem.
Also fix off-by-one in bounds checking of option processing.
Worst case scenario on that is a read one byte beyond the
end off a buffer with a crafted packet, and maybe therefore
a SIGV crash if the memory after the buffer is not mapped.
Thanks to Timothy Becker for spotting these.
From f3d832b41f44c856003517c583fbd7af4dca722c Mon Sep 17 00:00:00 2001
From: Neil Jerram <Neil.Jerram@metaswitch.com>
Date: Fri, 8 Apr 2016 19:23:47 +0100
Subject: [PATCH] Fix DHCPv4 reply via --bridge-interface alias interface
Sending a DHCPv4 reply through a --bridge-interface alias interface
was inadvertently broken by
commit 65c7212000
Author: Lung-Pin Chang <changlp@cs.nctu.edu.tw>
Date: Thu Mar 19 23:22:21 2015 +0000
dhcp: set outbound interface via cmsg in unicast reply
If multiple routes to the same network exist, Linux blindly picks
the first interface (route) based on destination address, which might not be
the one we're actually offering leases. Rather than relying on this,
always set the interface for outgoing unicast DHCP packets.
because in the aliasing case, iface_index is changed from the index of
the interface on which the packet was received, to be the interface
index of the 'bridge' interface (where the DHCP context is expected to
be defined, and so needs to be looked up).
For the cmsg code that the cited commit added, we need the original
iface_index; so this commit saves that off before the aliasing code
can change it, as rcvd_iface_index, and then uses rcvd_iface_index
instead of iface_index for the cmsg code.
Commit 51967f9807 began treating SERVFAIL
as a successful response from an upstream server (thus ignoring future
responses to the query from other upstream servers), but a typo in that
commit means that REFUSED responses are accidentally being treated as
successful instead of SERVFAIL responses.
This commit corrects this typo and provides the behaviour intended by
commit 51967f9: SERVFAIL responses are considered successful (and will
be sent back to the requester), while REFUSED responses are considered
unsuccessful (and dnsmasq will wait for responses from other upstream
servers that haven't responded yet).
server=/example.com/<ip-of-server>
The rationale is that the chain-of-trust will not be complete to
private servers. If it was, it would not be necessary to access the
server direct.
The list of exceptions to being able to locally answer
cached data for validated records when DNSSEC data is requested
was getting too long, so don't ever do that. This means
that the cache no longer has to hold RRSIGS and allows
us to lose lots of code. Note that cached validated
answers are still returned as long as do=0
Much gnarly special-case code removed and replaced with correct
general implementaion. Checking of zone-status moved to DNSSEC code,
where it should be, vastly simplifying query-forwarding code.
When we can validate a DS RRset, but don't speak the hash algo it
contains, treat that the same as an NSEC/3 proving that the DS
doesn't exist. 4025 5.2
Fix off-by-one in code which checks for over-long domain names
in received DNS packets. This enables buffer overflow attacks
which can certainly crash dnsmasq and may allow for arbitrary
code execution. The problem was introduced in commit b8f16556d,
release 2.73rc6, so has not escaped into any stable release.
Note that the off-by-one was in the label length determination,
so the buffer can be overflowed by as many bytes as there are
labels in the name - ie, many.
Thanks to Ron Bowes, who used lcmatuf's afl-fuzz tool to find
the problem.
Return INSECURE when validating DNS replies which have RRSIGs, but
when a needed DS record in the trust chain is proved not to exist.
It's allowed for a zone to set up DNSKEY and RRSIG records first, then
add a DS later, completing the chain of trust.
Also, since we don't have the infrastructure to track that these
non-validated replies have RRSIGS, don't cache them, so we don't
provide answers with missing RRSIGS from the cache.
If multiple routes to the same network exist, Linux blindly picks
the first interface (route) based on destination address, which might not be
the one we're actually offering leases. Rather than relying on this,
always set the interface for outgoing unicast DHCP packets.
The nasty code with static variable in retry_send() which
avoids looping forever needs to be called on success of the syscall,
to reset the static variable.
If the answer to an upstream query is a CNAME which points to an
A/AAAA record which also exists in /etc/hosts and friends, then
caching is suppressed, to avoid inconsistent answers. This is
now modified to allow caching when the upstream and local A/AAAA
records have the same value.
Make sure dst_addr is assigned the correct address in receive_query when OPTNOWILD is
enabled so the assigned mark can be correctly retrieved and set in forward_query when
conntrack is enabled.
Signed-off-by: Hans Dedecker <dedeckeh@gmail.com>
While testing https://github.com/sbyx/odhcp6c client I have noticed it
permanently crashes after startup.
The reason was it (odhcp6c) doesn't expect empty IA options in ADVERTISE
message without any suboptions.
Despite this validation bug of odhcp6c, dnsmasq should not generate
ADVERTISE messages with IA if there's nothing to advert per RFC 3315
17.2.2:
If the server will not assign any addresses to any IAs in a
subsequent Request from the client, the server MUST send an Advertise
message to the client that includes only a Status Code option with
code NoAddrsAvail and a status message for the user, a Server
Identifier option with the server's DUID, and a Client Identifier
option with the client's DUID.
Meanwhile it's need to add status code for every IA in REPLY message per
RFC3315 18.2.1:
If the server cannot assign any addresses to an IA in the message
from the client, the server MUST include the IA in the Reply message
with no addresses in the IA and a Status Code option in the IA
containing status code NoAddrsAvail.
So, I've changed the logic to skip IA completely from ADVERTISE messages and
to add NoAddrsAvail subcode into IA of REPLY messages.
As for overhead, yes, I believe it's ok to return NoAddrsAvail twice in IA
and in global section for compatibility with all old and new clients.
check_for_local_domain() was broken due to new code matching F_*
bits in cache entries for DNSSEC. Because F_DNSKEY | F_DS is
used to match RRSIG entries, cache_find_by_name() insists on an exact match
of those bits. So adding F_DS to the bits that check_for_local_domain()
sends to cache_find_by_name() won't result in DS records as well
as the others, it results in only DS records. Add a new bit, F_NSIGMATCH
which suitably changes the behaviour of cache_find_by_name().
This handles the case that more than one interface contains
the network the lease address is on, but the interfaces have different
prefix lengths. Use the longest prefix length.
- With nested prefixes reside on different interfaces of single host
(e.g., in 6to4, 2002::/16 on WAN and 2002:<IPv4>:<subnet>::/64 on LAN),
current matching mechanism might return the interface with shorter prefix
length instead of the longer one, if it appears later in the netlink message.
Signed-off-by: Lung-Pin Chang <changlp@cs.nctu.edu.tw>
This is useful when using dnsmasq as DHCP server for a set of VMs
whose data is routed by the host instead of being bridged. In this
scenario:
- There is an unbounded set of TAP interfaces that have no IP address
at the host end.
- DHCP allocation is done from an IPv4 address range associated with a
dummy interface.
- We run dnsmasq with --interface dummy --interface tap*
--bind-dynamic, so that it listens on all the TAP interfaces, and
--bridge-interface=dummy,tap*, so that it will allocate IP addresses
via the TAP interfaces from the range associated with the dummy
interface.
Some CNAMES left the value of ->uid undefined.
Since there are now special values if this, for CNAMES
to interface names, that could cause a crash
if the undefined value hit the special value.
Also ensure that the special value can't arise
when the uid is encoding the source of an F_CONFIG
record, in case there's a CNAME to it.
DNSSEC will eventually become opt-out and when that happens
I'll add libnettle build-depends. For now, build with
fakeroot debian/rules DEB_BUILD_OPTIONS=usednssec
to get DNSSEC support.
The linux kernel treats all addresses with a limited lifetime as being
non permanent, but when taking over the prefix livetimes from
upstream assigned prefixes through DHCP, addresses will always have a limited
lifetime.
Still reject temporary addresses, as they indicate autoconfigured
interfaces.
Contributed by T-Labs, Deutsche Telekom Innovation Laboratories
Signed-off-by: Jonas Gorski<jogo@openwrt.org>
Previously, if the DUID wasn't read from the lease-file or
script, a new one was created _after_ the helper process fork,
so for that first run, the script calls got an empty DUID.
Also, use a DUID_LL format DUID when there's no stable lease
storage, as well as when the RTC is broken. That has a chance of
evaluating to the same value on each startup.
Since owner and signer are both domain names and share the same
buffer in memory (daemon->namebuff), we need to go through a little
hoop to make sure one doesn't step on the other's toes. We don't
really need to extract the signer name until we have finished
calculating the hash of the RRset, so we postpone its extraction.
configuration - we have to read all the MAC addresses from netlink,
not bail when we find a suitable one.
Fix thinko in dhcp_update_configs - thanks to Hartmut for spotting
that.
Get a sensible address for the default DNS server even when using a
relay.
TODO
hostname handling.
update DHCP6 configs from dns
parse domain=<domain>,<IPv6 range>
pretty-print counted string options.
DECLINE messages
lease-script fro DHCPv6
I just wanted to let you know that I have built a Solaris .pkg install package of your dnsmasq utility for people to use. Feel free to point them in my direction if you have people who want this sort of thing.
I updated the try-all-ns patch to work with the latest version of git. Ended up implementing it on top of master, 2.78test2-7-g63437ff. As that specific if-clause has been changed in the last few commits, it's not compatible for 2.77, sadly.
dnsmasq comes with the possibility to run multiple systemd service instances on the same machine.
There is the main service which is enabled by default via `systemctl enable dnsmasq.service` and uses the configuration from `/etc/default/dnsmasq`.
Additional service instances can be enabled via `systemctl enable dnsmasq@<instance name>.service` that use the configuration from `/etc/default/dnsmasq.<instance name>`.
It is recommended to use a separate configuration file and directory for each instance.
Additionally make sure that all instances use either different ports and/or ip addresses to avoid binding collisions.
Example setup for an instance called "alt"
#1 File `/etc/dnsmasq.alt.conf` copied from `/etc/dnsmasq.conf`
#2 Directory `/etc/dnsmasq.alt.d`
#3 File `/etc/default/dnsmasq.alt` copied from `/etc/default/dnsmasq` with following adaptions:
* The options DNSMASQ_OPTS and CONFIG_DIR point to the correct configuration file and directory.
* If the additional instance should not use the machine's DNS resolver, normally that's the dnsmasq main instance, as upstream server, then the following addition could be used:
IGNORE_RESOLVCONF=yes
#4 Enable additional instance via `systemctl enable dnsmasq@alt.service`
#5 Start additional instance without reboot via `systemctl start dnsmasq@alt.service`
TODO
====
#1 - Found shortcoming on 2019-03-10
Only the option DNSMASQ_EXCEPT="lo" avoids that an DNS instance will be set as the machine's DNS resolver.
This may interfere with the wish to run an additional instance on a different port on the localhost addresses.
My suggestion in the initial Debian report [1] was to specify an explicit variable for this.
Should the variables DNSMASQ_INTERFACE and DNSMASQ_EXCEPT be used instead of --interface and --except-interface? (while "lo" still has to be in DNSMASQ_EXCEPT as of now)
Clarkconnect. It is also available as a FreeBSD port and is used in
Linksys wireless routers and the m0n0wall project.
<P>
Dnsmasq provides the following features:
The DNS subsystem provides a local DNS server for the network, with forwarding of all query types to upstream recursive DNS servers and
caching of common record types (A, AAAA, CNAME and PTR, also DNSKEY and DS when DNSSEC is enabled).
<DIR>
<LI>
The DNS configuration of machines behind the firewall is simple and
doesn't depend on the details of the ISP's dns servers
<LI>
Clients which try to do DNS lookups while a modem link to the
internet is down will time out immediately.
</LI>
<LI>
Dnsmasq will serve names from the /etc/hosts file on the firewall
machine: If the names of local machines are there, then they can all
be addressed without having to maintain /etc/hosts on each machine.
</LI>
<LI>
The integrated DHCP server supports static and dynamic DHCP leases and
multiple networks and IP ranges. It works across BOOTP relays and
supports DHCP options including RFC3397 DNS search lists.
Machines which are configured by DHCP have their names automatically
included in the DNS and the names can specified by each machine or
centrally by associating a name with a MAC address in the dnsmasq
config file.
</LI>
<LI>
Dnsmasq caches internet addresses (A records and AAAA records) and address-to-name
mappings (PTR records), reducing the load on upstream servers and
improving performance (especially on modem connections).
</LI>
<LI>
Dnsmasq can be configured to automatically pick up the addresses of
it's upstream nameservers from ppp or dhcp configuration. It will
automatically reload this information if it changes. This facility
will be of particular interest to maintainers of Linux firewall
distributions since it allows dns configuration to be made automatic.
</LI>
<LI>
On IPv6-enabled boxes, dnsmasq can both talk to upstream servers via IPv6
and offer DNS service via IPv6. On dual-stack (IPv4 and IPv6) boxes it talks
both protocols and can even act as IPv6-to-IPv4 or IPv4-to-IPv6 forwarder.
</LI>
<LI>
Dnsmasq can be configured to send queries for certain domains to
upstream servers handling only those domains. This makes integration
with private DNS systems easy.
</LI>
<LI>
Dnsmasq supports MX records and can be configured to return MX records
for any or all local machines.
</LI>
<LI>Local DNS names can be defined by reading /etc/hosts, by importing names from the DHCP subsystem, or by configuration of a wide range of useful record types.</LI>
<LI>Upstream servers can be configured in a variety of convenient ways, including dynamic configuration as these change on moving upstream network.
<LI>Authoritative DNS mode allows local DNS names may be exported to zone in the global DNS. Dnsmasq acts as authoritative server for this zone, and also provides
zone transfer to secondaries for the zone, if required.</LI>
<LI>DNSSEC validation may be performed on DNS replies from upstream nameservers, providing security against spoofing and cache poisoning.</LI>
<LI>Specified sub-domains can be directed to their own upstream DNS servers, making VPN configuration easy.</LI>
and Ilya Evseev has an article in Russian about dnsmasq to be found at <AHREF="http://ilya-evseev.narod.ru/articles/dnsmasq"> http://ilya-evseev.narod.ru/articles/dnsmasq</A>
<H2>License.</H2>
Dnsmasq is distributed under the GPL. See the file COPYING in the distribution
Dnsmasq is distributed under the GPL, version 2 or version 3 at your discretion. See the files COPYING and COPYING-v3 in the distribution
<inputtype="image"src="https://www.paypalobjects.com/en_US/GB/i/btn/btn_donateCC_LG.gif"border="0"name="submit"alt="PayPal – The safer, easier way to pay online.">
The source format is Inkscape SVG vector format, which is scalable and
easy to export to other formats. For convenience I've included a 56x31
png export and a 16x16 ico suitable for use as a web favicon.
Simon Kelley, 22/10/2010
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.