Many network administrators need to implement captive portal-like behavior where all DNS requests resolve to an internal IP address. This technique is commonly used in:
- Public WiFi hotspots
- Hotel networks
- Corporate guest networks
- Testing environments
The most efficient way to accomplish this is using dnsmasq, a lightweight DNS forwarder. While the original approach mentioned adding TLDs individually works, it's not scalable or comprehensive.
Here's the proper way to configure dnsmasq to intercept all DNS queries:
# /etc/dnsmasq.conf
# Redirect all domains to 192.168.2.1
address=/#/192.168.2.1
# Optional: Keep local domain resolution
local=/local/
domain=local
expand-hosts
For more control over the redirection:
# Redirect specific domains differently
address=/example.com/192.168.2.1
address=/test.local/192.168.2.2
# Exclude certain domains from redirection
server=/google.com/8.8.8.8
server=/microsoft.com/8.8.4.4
# Set TTL for better client caching
local-ttl=300
After modifying the configuration, restart dnsmasq and test:
sudo systemctl restart dnsmasq
nslookup anydomain.com 127.0.0.1
dig @127.0.0.1 anything.org
Modern browsers may warn users about HTTPS connections. Consider these additional steps:
# iptables rules for HTTP/HTTPS redirection
iptables -t nat -A PREROUTING -i wlan0 -p tcp --dport 80 -j DNAT --to-destination 192.168.2.1:80
iptables -t nat -A PREROUTING -i wlan0 -p tcp --dport 443 -j DNAT --to-destination 192.168.2.1:443
When setting up a captive portal for public WiFi access (like hotels or coffee shops), we often need to intercept all DNS requests and redirect them to an internal web server hosting the authentication page. While we can manually specify common TLDs in dnsmasq configuration, this approach isn't comprehensive enough.
Instead of listing every possible TLD, we can leverage dnsmasq's wildcard functionality to catch all domains:
# /etc/dnsmasq.conf
# Wildcard address mapping
address=/#/192.168.2.1
The #
character acts as a wildcard that matches any domain. This single line will redirect all DNS queries to 192.168.2.1.
After making changes to dnsmasq.conf, restart the service:
sudo systemctl restart dnsmasq
Test the configuration with:
dig example.com @localhost
nslookup google.com 127.0.0.1
Both commands should return 192.168.2.1 as the resolved address.
For more sophisticated setups, consider these additional configurations:
# Only respond to queries from wireless interface
interface=wlan0
# DHCP configuration for captive portal networks
dhcp-range=192.168.2.100,192.168.2.200,12h
dhcp-option=option:router,192.168.2.1
If DNS resolution isn't working as expected:
- Check dnsmasq logs:
journalctl -u dnsmasq
- Verify dnsmasq is binding to correct interface:
netstat -tulnp | grep dnsmasq
- Ensure no other DNS service is running on port 53
When implementing this solution:
- Use firewall rules to prevent bypassing the captive portal
- Consider rate limiting to prevent DNS amplification attacks
- Implement HTTPS properly on your captive portal to avoid certificate warnings