Creating a Raspberry Pi 5 access point with Pi-hole

Hullo, I apologize if this is an inappropriate place to ask this question. I have an issue that has been plaguing me for days and I have no idea how to fix it, so I figure someone here would have an idea on what to do.

For the past few days I’ve been attempting to get a basic configuration set up on my recently-acquired Raspberry Pi 5 that will allow me to host a wireless access point to devices in my household, with Pi-hole integrated within. Currently I have an Xfinity router that every device is connected to (I live in a shared household), with a “reserved IP” designated for the Pi (10.0.0.2) which is also connected to it. I assume this is practically the same thing as a static IP. Since other devices use the main router I can’t turn off its DHCP for Pi-hole if that’s required.

I am currently trying to use hostapd with Pi-hole being used in place of dnsmasq. As usual, I have Ethernet connected to the router via end0, and I have the wireless radio at wlan0.

Every attempt I’ve made to get this working thus far has invariably resulted in failure. The closest I’ve gotten is a network that is discoverable and connectable, but that strangely boots out any device that attempts to connect to it. I don’t see this getting logged, so I don’t know what it is, and I can only assume it has something to do with a DHCP misconfiguration (or the lack thereof). I’ve only been testing this on my phone as my main PC uses Ethernet. On said phone (Android, if it matters), I tap on the network, enter the password (which I am aware is currently world-readable at the moment; it’s something I’ll fix after I get this setup working), and attempt to establish a connection, but instantly the connection is severed and I start auto-connecting to my router’s Wi-Fi instead. Again, this is not logged anywhere, including logcat, so I don’t definitively know what the problem is.

Let me outline precisely what I want the outcome of this to be: my Pi, acting as its own Wi-Fi network that devices can connect to, that blocks ads &c. with Pi-hole, and that is able to connect to the Internet through my router. I’m only slightly knowledgeable on networking, so much of this has been stumbling around in the dark. I’m typically averse to posting on forums, but I’m getting restless after close to four days straight of attempting to troubleshoot this.

My configuration for the machine is at this location. r5e.containers.pihole is just a wrapper around a Docker container. If it’s at all relevant, I do intend to put other services (Docker containers, probably a pastebin at least) on the Pi, which I’d like for devices connected to both it and the regular upstream router to be able to access.

	virtualisation.docker.enable = true;
	r5e.containers = {
		pihole = {
			enable = true;
			dhcp.enable = true;
			listenPortHTTP = 8080;
			listenPortHTTPS = 8443;
			openFirewall = true;
		};
	};

	services = {
		hostapd = {
			enable = true;
			radios.wlan0 = {
				band = "2g";
				channel = 7;
				countryCode = "US";
				networks.wlan0 = {
					authentication = {
						mode = "wpa2-sha256";
						wpaPassword = "techcat8";
					};
					logLevel = 1;
					ssid = "near";
				};
				settings = {
					ht_capab = lib.mkForce "[HT40][SHORT-GI-20]";
				};
			};
		};
	};

	networking = {
		# bridges.br0 = {
		# 	interfaces = [ "end0" "wlan0" ];
		# };
		firewall = {
			allowedTCPPorts = [ 22 ];
			extraCommands = ''
				iptables -t nat -A POSTROUTING -o end0 -j MASQUERADE
			'';
		};
		hostName = "near";
		interfaces = {
			# br0 = {
			# 	ipv4.addresses = [
			# 		{
			# 			address = "10.0.0.2";
			# 			prefixLength = 24;
			# 		}
			# 	];
			# };
			end0.useDHCP = true;
			wlan0.useDHCP = true;
		};
		networkmanager.unmanaged = [ "interface-name:wlan*" ];
		useDHCP = false;
		wireless.enable = true;
	};

Okay a, first things first. Can you connect to the PI at all when it’s acting as an access point? If so what IP address etc are you assigned when you do so?

Another thing, If you can access the pi via ssh or directly, what is the information output from ‘ip addr’?

My initial thought is if you have the pi also trying to give out DHCP addresses as well as your router you’ll be having issues and things won’t work.

  • In most cases, I can SSH into it just fine. This includes when I try to setup the AP using create_ap, which I had only used to ensure that things were actually capable of working properly. Most of the time, when trying to switch the configuration with nixos-rebuild switch --flake [blabla] --target-host root@near.local after assigning a static IP to an interface or modifying Pi-wall's firewall (I think? the latter case was particularly strange), the device completely locks up and I can't do anything. Usually, this manifests in nixos-rebuild hanging on Restarting the following services: dhcpcd.service. Most commonly, uncommenting the br0 lines causes this.

    After a lot of horribly inefficient processes of having to re-flash the OS onto the SD card since it was now inaccessible over SSH ("Destination Host Unreachable", or something along those lines), I managed to plug it in to my TV and type into it with my keyboard so that I could better understand what's going on. Sometimes wlan0 would be down and the Internet would be inaccessible (DHU), or both would be up and the Internet would be accessible but nothing in the LAN could reach the Pi itself.

    Typing this now I realize you're probably referring to connecting to it as an access point, and the answer is unfortunately no. When I was using create_ap instead of hostapd just to see if things had the potential to work, it did work perfectly (minus Pi-hole not being there, which I was unable to fix), and I was able to connect and access the Internet through my phone connected to the AP. However, beyond that, I have had no success.
  • [root@near:~]# ip addr
    1: lo:  mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
        link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
        inet 127.0.0.1/8 scope host lo
           valid_lft forever preferred_lft forever
        inet6 ::1/128 scope host noprefixroute 
           valid_lft forever preferred_lft forever
    2: end0:  mtu 1500 qdisc fq_codel state UP group default qlen 1000
        link/ether 2c:cf:67:04:a4:b8 brd ff:ff:ff:ff:ff:ff
        inet 10.0.0.2/24 brd 10.0.0.255 scope global dynamic noprefixroute end0
           valid_lft 172656sec preferred_lft 151056sec
        inet6 2601:348:600:4130::76b1/128 scope global dynamic noprefixroute 
           valid_lft 604654sec preferred_lft 604654sec
        inet6 2601:348:600:4130:9ba:4a44:46a8:20ef/64 scope global temporary dynamic 
           valid_lft 85649sec preferred_lft 85649sec
        inet6 2601:348:600:4130:2ecf:67ff:fe04:a4b8/64 scope global dynamic mngtmpaddr noprefixroute 
           valid_lft 85649sec preferred_lft 85649sec
        inet6 fe80::2ecf:67ff:fe04:a4b8/64 scope link 
           valid_lft forever preferred_lft forever
    3: wlan0:  mtu 1500 qdisc fq_codel state UP group default qlen 1000
        link/ether 2c:cf:67:04:a4:b9 brd ff:ff:ff:ff:ff:ff
        inet 169.254.152.94/16 brd 169.254.255.255 scope global noprefixroute wlan0
           valid_lft forever preferred_lft forever
        inet6 fe80::2ecf:67ff:fe04:a4b9/64 scope link 
           valid_lft forever preferred_lft forever
    4: docker0:  mtu 1500 qdisc noqueue state DOWN group default 
        link/ether 02:42:14:0b:95:fb brd ff:ff:ff:ff:ff:ff
        inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
           valid_lft forever preferred_lft forever
  • This is what I assumed to be the problem and so I doubted whether hosting a DHCP server on Pi-hole was a good idea. I initially added the dhcp.enable switch so I could disable it outright, and disabled is where it's at right now. I do wonder if there is a way to separate two DHCP servers right now, or if it's not possible or not worth pursuing in this context. I assume both are true.

I haven’t read the whole thread, but some comments:

  • The raspberry pi 5 doesn’t support WPA3 (yes, seriously), you have to use wpa2-sha1.
  • use networking.interfaces to setup the bridge and don’t touch NetworkManager or wpa_supplicant (networking.wireless)
  • Do one thing a time: try to get it to work just as an access point (remove that NAT rule etc.).

Here’s a working network configuration for an acesss point on the raspberry pi 5:

{
  networking.usePredictableInterfaceNames = false;

  # Bridges for wired to wireless
  networking.bridges.br0.interfaces = [ "eth0" ];

  # change MAC address
  networking.interfaces.eth0.macAddress = "00:68:eb:26:b2:42";
  networking.interfaces.br0.macAddress =  "00:68:eb:26:b2:43";

  # Enable forwarding packets
  boot.kernel.sysctl = {
    "net.ipv6.conf.all.forwarding" = 1;
    "net.ipv4.conf.all.forwarding" = 1;
  };

  # Create an access point
  services.hostapd.enable = true;
  services.hostapd.radios.wlan0 =
    { band = "5g";
      channel = 0;
      countryCode = "PA";
      wifi4.capabilities =
        [ "HT40+" "SHORT-GI-20" "SHORT-GI-40" "MAX-AMSDU-3839" "DSSS_CCK-40" ];
      wifi5.capabilities = [ "MAX-MPDU-3895" "SHORT-GI-80" "SU-BEAMFORMEE" ];
      wifi5.operatingChannelWidth = "80";
      networks.wlan0 =
        { ssid = "near";
          bssid = "f8:0d:ac:60:E0:f9";
          authentication.mode = "wpa2-sha1";
          authentication.wpaPassword = "techcat8";
          settings.bridge = "br0";
        };
    };

}

If you want I can give you the full configuration to build the SD image.

2 Likes

Thank you very much! Is wpa2-sha256 also not supported? Additionally, there’s a few more things I’m curious about:

  • For the Wi-Fi capabilities, I can make out “beamformee” and such but the rest is all Greek to me. Where do you obtain these values and/or know which ones are appropriate?
  • For the MAC addresses, I just took what was specified by ip addr, I assume this is okay. I’m more confused about how to obtain the BSS ID. The documentation says to “try assigning related addresses from the locally administered MAC address ranges, by reusing the hardware address but replacing the second nibble with 2, 6, A or E”, but honestly I’m not sure how to retrieve such related addresses, or the locally administered MAC address ranges. Forgive my ignorance here.
  • Is there a reason usePredictableInterfaceNames is disabled? I’m assuming this is because there is only one WLAN and one Ethernet port on the Pi so needing to differentiate between any devices of the same type is superfluous. Should I re-enable this if I add, e.g., a Wi-Fi adapter?

And yes, I would much appreciate the full configuration.

Is wpa2-sha256 also not supported?

Not supported, yes.

Where do you obtain these values and/or know which ones are appropriate?

These are all the capabilities reported by the wifi chip on the raspberry pi 5.

If you want to verify, look at the output of iw phy phy0 info, there is a “Capabilities” bitmask in hex, which lists them. To convert them to the costants used by hostapd, I think I repurposed the openwrt script that generates the wireless configuration (/lib/netifd/wireless/mac80211.sh).

For the MAC addresses, I just took what was specified by ip addr , I assume this is okay.

Yes, but you can literally put anything you like, as long as it’s valid.

or the locally administered MAC address ranges. Forgive my ignorance here.

It just means your MAC address, you’re the admin here.

Is there a reason usePredictableInterfaceNames is disabled

Just to make to make the configuration reproducible, you never know what crazy names systemd will assign.

And yes, I would much appreciate the full configuration.

Here’s an archive.