I configured Pi-Hole as a DHCP server, too. I disabled the DHCP service in the router.
After couple of days everything has been working properly, clients stopped assigning the offered IPs.
DHCP Settings
DHCP server enabled
Make sure your router's DHCP server is disabled when using the Pi-hole DHCP server!
Range of IP addresses to hand out
From
192.168.0.100
To
192.168.0.199
Router (gateway) IP address
Router
192.168.0.1
Advanced DHCP settings
Pi-hole domain name
Domain
DHCP lease time
Lease time in hours
Hint: 0 = infinite, 24 = one day, 168 = one week, 744 = one month, 8760 = one year
Enable DHCPv4 rapid commit (fast address assignment)
Enable IPv6 support (SLAAC + RA)
cat /var/log/pihole.log:
Feb 4 16:23:22 dnsmasq-dhcp[3048]: DHCPDISCOVER(eth0) 42:0c:99:21:aa:xx
Feb 4 16:23:22 dnsmasq-dhcp[3048]: DHCPOFFER(eth0) 192.168.0.180 42:0c:99:21:aa:xx
Feb 4 16:24:25 dnsmasq-dhcp[3048]: DHCPDISCOVER(eth0) 42:0c:99:21:aa:xx
Feb 4 16:24:25 dnsmasq-dhcp[3048]: DHCPOFFER(eth0) 192.168.0.180 42:0c:99:21:aa:xx
pi@raspberrypi:~ $ cat /etc/dnsmasq.d/01-pihole.conf
addn-hosts=/etc/pihole/local.list
addn-hosts=/etc/pihole/custom.list
localise-queries
no-resolv
cache-size=10000
log-queries
log-facility=/var/log/pihole.log
log-async
server=84.2.44.1
server=1.1.1.1
domain-needed
expand-hosts
bogus-priv
local-service
dhcp-name-match=set:hostname-ignore,wpad
dhcp-name-match=set:hostname-ignore,localhost
dhcp-ignore-names=tag:hostname-ignore
pi@raspberrypi:~ $ cat /etc/dnsmasq.d/02-pihole-dhcp.conf
dhcp-authoritative
dhcp-range=192.168.0.100,192.168.0.199,24h
dhcp-option=option:router,192.168.0.1
dhcp-leasefile=/etc/pihole/dhcp.leases
#quiet-dhcp
domain=lan
local=/lan/
pi@raspberrypi:~ $ cat /etc/dnsmasq.conf
conf-dir=/etc/dnsmasq.d
pi@raspberrypi:~ $ cat /etc/dhcpcd.conf
# A sample configuration for dhcpcd.
# See dhcpcd.conf(5) for details.
# Allow users of this group to interact with dhcpcd via the control socket.
#controlgroup wheel
# Inform the DHCP server of our hostname for DDNS.
hostname
# Use the hardware address of the interface for the Client ID.
clientid
# or
# Use the same DUID + IAID as set in DHCPv6 for DHCPv4 ClientID as per RFC4361.
# Some non-RFC compliant DHCP servers do not reply with this set.
# In this case, comment out duid and enable clientid above.
#duid
# Persist interface configuration when dhcpcd exits.
persistent
# Rapid commit support.
# Safe to enable by default because it requires the equivalent option set
# on the server to actually work.
option rapid_commit
# A list of options to request from the DHCP server.
option domain_name_servers, domain_name, domain_search, host_name
option classless_static_routes
# Respect the network MTU. This is applied to DHCP routes.
option interface_mtu
# Most distributions have NTP support.
option ntp_servers
# A ServerID is required by RFC2131.
require dhcp_server_identifier
# Generate SLAAC address using the Hardware Address of the interface
#slaac hwaddr
# OR generate Stable Private IPv6 Addresses based from the DUID
slaac private
# Example static IP configuration:
#interface eth0
#static ip_address=192.168.0.10/24
#static ip6_address=fd51:42f8:caae:d92e::ff/64
#static routers=192.168.0.1
#static domain_name_servers=192.168.0.1 8.8.8.8 fd51:42f8:caae:d92e::1
# It is possible to fall back to a static IP if DHCP fails:
# define static profile
#profile static_eth0
#static ip_address=192.168.1.23/24
#static routers=192.168.1.1
#static domain_name_servers=192.168.1.1
# fallback to static profile on eth0
#interface eth0
#fallback static_eth0
interface wlan0
static ip_address=192.168.0.201/24
static routers=192.168.0.1
static domain_name_servers=192.168.0.200
interface eth0
metric 100
static ip_address=192.168.0.200/24
static routers=192.168.0.1
static domain_name_servers=192.168.0.200
There is a config like this, too, but not sure it is something that is active:
pi@raspberrypi:~ $ cat /etc/dhcp/dhclient.conf
# Configuration file for /sbin/dhclient.
#
# This is a sample configuration file for dhclient. See dhclient.conf's
# man page for more information about the syntax of this file
# and a more comprehensive list of the parameters understood by
# dhclient.
#
# Normally, if the DHCP server provides reasonable information and does
# not leave anything out (like the domain name, for example), then
# few changes must be made to this file, if any.
#
option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;
send host-name = gethostname();
request subnet-mask, broadcast-address, time-offset, routers,
domain-name, domain-name-servers, domain-search, host-name,
dhcp6.name-servers, dhcp6.domain-search, dhcp6.fqdn, dhcp6.sntp-servers,
netbios-name-servers, netbios-scope, interface-mtu,
rfc3442-classless-static-routes, ntp-servers;
#send dhcp-client-identifier 1:0:a0:24:ab:fb:9c;
#send dhcp-lease-time 3600;
#supersede domain-name "fugue.com home.vix.com";
#prepend domain-name-servers 127.0.0.1;
#require subnet-mask, domain-name-servers;
#timeout 60;
#retry 60;
#reboot 10;
#select-timeout 5;
#initial-interval 2;
#script "/sbin/dhclient-script";
#media "-link0 -link1 -link2", "link0 link1";
#reject 192.33.137.209;
#alias {
# interface "eth0";
# fixed-address 192.5.5.213;
# option subnet-mask 255.255.255.255;
#}
#lease {
# interface "eth0";
# fixed-address 192.33.137.200;
# medium "link0 link1";
# option host-name "andare.swiftmedia.com";
# option subnet-mask 255.255.255.0;
# option broadcast-address 192.33.137.255;
# option routers 192.33.137.250;
# option domain-name-servers 127.0.0.1;
# renew 2 2000/1/12 00:00:01;
# rebind 2 2000/1/12 00:00:01;
# expire 2 2000/1/12 00:00:01;