Thursday, October 26, 2023

Orange PI Zero 3 - Initial Set Up, DDNS, and WireGuard Configuration



This is a multipart article wrapped into one. We'll use the Orange PI Zero 3 as a DDNS update client, Pi-hole server, and as a WireGuard server. This will assume you've read and setup the pi already. (INSERT ARTICLE HERE ABOUT GENERAL SETUP). We'll load some cool tools for administering the network as well.

This entire thing started when you could no longer buy a Raspberry PI for $35.

Usually NVR camera systems will include some sort of dynamic dns service or allow you to use your own update URL. I had the "pleasure" of working on a Speco NVR unit. If you've never heard of them stay away, they're akin with the no name systems sold in big box stores. Five minutes with this thing and you'll want to throw it out a window. There's tons of standard features that are nowhere to be found on these units. I've seen cheaper noname brands that include more functionality.

This particular Speco VX NVR only includes their own ddns service (which does not work) and contains no alternative options. They do not give you the option to use popular services such as "no-ip" or "dyndns". Usually you can get away with using the "dyndns" update url with your own service. Nope, not this time.

In comes the Raspberry PI, great idea but still (10/2023) ridiculously overpriced by scalpers, so this is a no go. Orange PI looks like a viable alternative on paper at a quarter of the cost and is currently in stock.

I'm using the Orange PI Zero 3 for this (tested with 1 & 2gb version). Amazon had them delivered the same day.

Since there are no commercial cases available I have modified another design to include a spot for velcro and or hidden drywall screws. I've also modified it to take the el cheapo Amazon stainless metric socket cap screws that have a splined design on the cap side. My local hardware store has the smooth side version (18-8) which is why they fit easily on the first print.

I can only find two types socket cap screws from McMaster-Carr that fit the bill for this design. One has a smooth side and is labeled " 18-8 Stainless Steel Socket Head Screws" and the other " Super-Corrosion-Resistant 316 Stainless Steel Socket Head Screws" is overkill for this design but I suspect it's what the Chinese have sloppily copied and are reselling on Amazon.

I believe the original designer of this case used the CAD files in Fusion 360 of the 18-8 screws and not a physical measurement of the Amazon specials.

I'm in the process of redesigning this case from the ground up to make the installation easier. DDNS Update Client Setup:

First off we need a way to update the DDNS name whenever the IP changes (modem replaced, etc.). has been great other than their email service toboggle earlier in the year. Their DDNS service is cheap and updates fast..

This was adapted from "". Steps have been added to ensure it works correctly. You want to make sure the group is set for only the location you're working on or else there's a chance it'll update every DDNS name in your account with the same IP. Ask me how I know. DDNS Backend Setup:
  1. Log in to and go to DDNS Services.
  2. Click "Add" in the top right corner.
  3. Using your own domain name on the right side enter:
  4. Set the IP address to and save.
  5. Click on "Groups" on the right side.
  6. Create a new group named:
    1. customnamexyzcom (make sure there's no periods).
    2. Save and go back a page.
  7. Assign the new group to the new custom ddns name.
  8. Done.

Dynu DDNS Setup on the PI:

*By default the Orange PI will be setup for DHCP after burning the image so check your router, use "sudo netdiscover -r" and wait, or use "arp -a" under Linux. Use "netdiscover" if your device cannot be found by other means.

*This can be setup prior to getting to the cx's location.
  1. Login to the Orange PI (non root user)
    1. orangepi/orangepi
  2. We'll change the password later to key authentication
  3. Create the folder for the update script:
    1. cd ~
    2. mkdir dynudns
    3. cd dynudns
  4. Create update script (don't miss the hyphen at the end):
    1. nano
    2. echo url="" | curl -k -o ~/dynudns/dynu.log -K -
      1. Fill in the username with your service login for
      2. The password can be the hashed client password
      3. CTRL + X then Y to save and exit.
    3. Make "" executable:
      1. chmod 700
    4. Use a cron job to make the script run every 5 minutes:
      1. crontab -e
      2. Add the following to the bottom of the crontab:
        1. */5 * * * * ~/dynudns/ >/dev/null 2>&1
    5. Reboot the Orange PI:
      1. sudo reboot
    6. Refresh and verify IP address has updated.
    7. Done.

Initial setup of the OPZ3 - Get Connected:

Titles not marked with a star are mandatory!

1. Burn "Orangepizero3_1.0.2_debian_bookworm_server_linux6.1.31.img" to a MicroSD card using Win32DiskImager.

1a. Included in the ZIP file is a SHA256 hash of the included IMG file. In Win32DiskImager import the IMG file first, then press "generate". This will create a hash from the imported IMG file so you can verify it against the included SHA file. Once verified, burn "Orangepizero3_1.0.2_debian_bookworm_server_linux6.1.31.img" to a MicroSD card.

2. Hook into the serial port using PuTTY or Terminal with a serial to UART adapter.
  • 115,200/8/1, NO FLOW CONTROL

3. Enable VT100

4. Attach ethernet and boot it up. You should see something similar to...

  • $ means you're logged in as a normal user, you can use "su" to obtain root
  • # means you're logged in as root

Change the root and default users password:

The default password for both the "root" and "orangepi" accounts are "orangepi".

1. Change the password for the "root" account:

sudo passwd root

2. Change the password for the user "orangepi":


Disable users from automatically logging in upon reboot:

Refer to the prior image and above the login banner you can see "orangepizero3 login: orangepi (automatic login)" displayed.

When the pi reboots or is manually power cycled the default user "orangepi" will automatically be logged into a session. We don't want this because that means anyone with physical serial access can connect and automatically gain access to that user's shell. If you didn't change the root password at this point then all it takes is "sudo login root", type in the default password twice and you're in.

1. Disable automatic login and reboot to view changes:

sudo -d

sudo reboot

**Highly suggested against, but if you want a user to automatically be logged in at boot time (replace USERNAME with either "root" or "orangepi") and reboot:


sudo reboot

Change SSH Port:

The default port is 22 and we will change it to 2222 for this example.

I'm seeing two locations on this Debian installation:

sudo find / -name "sshd_config" -print

  1. /etc/ssh/sshd_config
  2. /usr/share/openssh/sshd_config
Number one is system wide so we're going to edit that one only.

sudo nano /etc/ssh/sshd_config

Uncomment the line "Port 22" and change it to "Port 2222" so it looks like the image below:

If disabling root login which is highly suggested, leave this window open and continue on. If not save and exit.

Disable root Login via SSH:

We should also disable root login while we're in here.

1. Page down and look for "PermitRootLogin yes" and change "yes" to "no".

2. CTRL + X then Y then Enter to save and quit nano. Reboot when finished.

sudo reboot

  • You can get to elevated root by typing "su" before a command and typing the password for the "orangepi" user.
  • You can login directly as root via serial access but not via SSH.

*To view connected users:

who -a

    *To continuously watch for connected users:

    watch who -a

      CTRL + C to quit this screen.

      Install netdiscover:

      Need to find an IP that's on a different subnet? Does not discover VLANS.
      1. sudo apt install netdiscover
      2. netdiscover -r

      sudo apt update
      sudo apt upgrade

      sudo apt install netdiscover

      sudo netdiscover -r

      Install Screen (already included with image):

      sudo apt update
      sudo apt upgrade

      sudo apt install screen

      # To start


      # To reattach

      screen -r

      Disable Password Based Authentication & Enable Public Key Authentication:

      1. Open PuTTY Key Generator.

      2. Bottom right change 2048 bits to 4096 bits.

      3. Press "Generate" above and move the mouse to generate randomness.

      4. Insert a "key passphrase" and confirm it again. The passphrase is used to encrypt the private key.

      Test Keys Used

      5. Save the private key to your computer as "rsa-key-SERVERNAME.ppk".

      6. On the pi in the orangepi user's home folder, create a folder called ".ssh" using mkdir.
      • mkdir /home/orangepi/.ssh/
      8. Create a new file using nano in the ".ssh" folder called "authorized_keys" and paste in the contents of the public key from the key generator into the file. Save and exit nano.
      • nano /home/orangepi/.ssh/authorized_keys
      9. Check and make sure the "authorized_keys" file looks like this (needs to be on one line):
      • ssh-rsa  THEACTUALKEY  rsa-key-SERVERNAME
      10. Change the file permissions:
      • chmod 700 /home/orangepi/.ssh
      • chmod 600 /home/orangepi/.ssh/authorized_keys
      11. Configure the SSH server details:
      • sudo nano /etc/ssh/sshd_config
      • Change "PubkeyAuthentication" from NO to YES.
      • Change "PasswordAuthentication" to NO.
      • Change "UsePAM" from YES to NO.
      12. Restart the ssh service
      • sudo systemctl restart ssh
      13. Open PuTTY --> Connection --> SSH --> Auth --> select "rsa-key-SERVERNAME.ppk" (private key).

      14. Go back to the session tab and give the PuTTY profile an IP address, port, name, and save.

      15. Now when connecting PuTTY will ask for the username and passphrase.

      Install UFW (Uncomplicated Firewall):

      This will be the front end for iptables.

      sudo apt update
      sudo apt upgrade

      sudo apt install ufw

      UFW is disabled by default and you need to open the ports you want before enabling it or you'll lock yourself out.

      Allow port 2222 TCP for SSH:

      sudo ufw allow 2222/tcp comment 'SSH'

      Show Firewall Rules Currently Enabled:

      sudo ufw show added

      Enable / Disable UFW:

      sudo ufw enable

      sudo ufw disable

      View the status of the firewall:

      sudo ufw status

      Disable IPv6 on the Orange PI Zero 3 (optional):

      Pull up the config:

      sudo orangepi-config

      1. Select "Network".

      2. Select "IPV6" to disable IPv6. When done it should say "Enable IPv6 for APT and system".

      Remove Unnecessary Features:

      1. Remove "IR Support".

      2. Remove "Bluetooth Support".

      3. Set a static IP of,, or (the adapter name is "end0").

      4. Set a DHCP reservation in the router as well and while there, port forward your WireGuard UDP port. You'll chose them when we do the PiVPN setup later.

      Extra Settings:

      1. Configure timezone.

      2. Change hostname.

      3. Pi-hole (will add to this article at a later date)


      Pi-hole is a dns sinkhole to protect devices from unwanted content on the web.

      By this point you should have the OP3 up and running with UFW installed. We're going to install Pi-hole in this section.

      W'll install Pi-hole first as the PiVPN script (heavily adapted from Pi-hole) can detect if Pi-Hole is already installed and will offer to use it as DNS for the VPN clients.

      Start Pi-hole Setup:


      curl -sSL | bash

      Make sure the Orange PI has a static IP address before continuing!

      Pick "end0" as this is the wired interface.

      Choose upstream DNS provider (after filtering by Pi-hole who do we send DNS requests to):

      For the initial config use StevenBlack's Unified Hosts List. You can get more lists here.

      We need a visual way to manage Pi-hole. Select "Yes" to install the Admin Web Interface.

      Install "lighttpd" web server and required PHP modules.

      Using privacy levels you can specify which level of detail you want to see in your Pi-hole statistics. The privacy level may be changed at any time without having to restart the DNS resolver. Note that queries with (partially) hidden details cannot be disclosed with a subsequent reduction of the privacy level. They can be changed either from the Settings page on the dashboard or in FTL's config file.

      Explanation of "Privacy Levels".

      Choose "0" to hide nothing. All statistics are available.

      The script will install required packages at this point.

      ๐Ÿคธ‍♂️ - Picture not included

      When the installation is complete you will be given the following 3 pieces of information:
      1. The IP address of the device to use as a DNS server
      2. The link to access the web interface
      3. The admin web page login password.

      Press "OK" to bring you back to the command prompt. Remember you're elevated as root "#". Type "exit" to return to the user prompt "$".

      Pi-hole Web Interface:

      At this point you can call up the admin web interface to manage Pi-hole using the above addresses. "http://pi.hole/admin" probably won't work since the device already had the host name changed earlier to "orangepizero3".

      So "http://orangepizero3/admin" will work instead.

      If you're using pfSense as your router and the above link does not work, try pinging the hostname of the device. If it fails have a look at my other article, "".

      Use the password given to you at the end of the installation to login.

      Web Interface:

      This is the main interface. From here you can view total queries, client activity, top domains, top clients, etc. Settings are on the left side.

      Documentation is here:

      Change the admin web password:

      Assuming you still have the SSH connection to the pi open...

      Set a new password for the web interface:

      pihole -a -p

      Change Celsius in the web interface to Fahrenheit:

      pihole -a -f

      Moar Commands:

      pihole -h

      Admin Commands:

      pihole -a -h

      Ad Lists:

      If you recall during the set up phase the installer suggested we use "StevenBlack's Unified Hosts List (with base extensions)" to get started blocking ads and what not. "This hosts file is a merged collection of hosts from reputable sources with a dash of crowd sourcing via GitHub". As of the time of writing this list contains 154,802 entries.

      Adding Additional Ad Lists:

      Pi-hole --> Adlists --> Add (right side)

      You may want to spend some time on Steven Blacks site and read, read, read before adding more lists to make sure you are targeting the correct audience.

      Let's say we want to block "Unified Hosts + fake news + gambling + porn + social" websites. You'd use this link "".

      In the image above you'd add that URL to the address section, give the list the following description "SB - Unified Hosts + fake news + gambling + porn + social" and hit add.

      able the original Unified Hosts list since we've already got it included in the new link.

      Notice the question mark to the left of our new list. Click it and you'll see the list has not been downloaded yet.

      You'll need to update your gravity list after modifying the adlists.

      This can be achieved by either running the command below or by going to "Tools --> Update Gravity". This will go out and retrieve the new list(s) and load them in.

      pihole -g

      Add UFW Allow Rule for Admin Web Interface:

      Pi-hole doesn't seem to modify UFW to allow access to the admin web interface after it's install. Add the following rule to allow traffic to the admin web interface of Pi-hole:

      sudo ufw allow 80 comment 'Pi-hole Web Interface' - Displays LightTPD

      Using Pi-hole DNS on Workstations:

      Now all you need to do is point your devices or router to "orangepizero3" or "" in this example to start taking advantage of this dns server.

      We'll setup PiVPN next to take advantage of this new DNS sinkhole server for remote clients. UFW will check to see if Pi-hole is installed and will offer to use it.

      Pi-hole Auto Updates?

      Probably not a good idea to fully automate this as seen here:

      PiVPN Set Up (openvpn & wireguard):

      Make sure UFW is enabled and your SSH port is forwarded since this script will makes changes that can potentially break UFW at the moment.

      curl -L | bash

      Initial Screen

      Static IP Warning

      IPv6 Leak Warning

      Static IP Non-Raspberry PI Warning

      Choose local user info screen

      Pick the "orangepi" user

      Type in password for "orangepi" user.

      Select WireGuard or OpenVPN

      Pick WireGuard or OpenVPN here to be taken to the appropriate instructions.

      OpenVPN Set Up (client does not require elevated privileges) (slower throughput than wireguard):
      • OpenVPN uses UDP port 1194 and TCP port 443 by default.
      • It's recommended to change the UDP port to something in the dynamic port range of 49152–65535.
      • In our example we'll use the default port for OpenVPN.
      *So far we should have UFW installed and enabled and Pi-hole installed and configured.

      If Pi-hole is detected it will use that as the VPN DNS. If you select "No" it will send you to the DNS Provider page.

      Uninstalling PiVPN will uninstall UFW.

      curl -L | bash

      UFW needs to be installed and enabled prior to running PiVPN.
      sudo apt install ufw.

      WireGuard Set Up (client requires elevated privileges!!) (faster throughput than OpenVPN):
      • WireGuard uses port 51820 by default.
      • It's recommended to change this to something in the dynamic port range of 49152–65535.
      • In our example we'll use the default port for WireGuard.
      For the example we'll use the default port of 51820.

      Verify the port number.

      Choose DNS resolver for VPN clients (scroll for more).

      There are multiple choices here and only one can be picked. If Pi-hole is already installed the PiVPN installer will ask if you want to use this as the DNS server.

      If you pick one then change your mind, cancel and rerun the installer.

      As per the install script this is the full list (10/2023):











      Allow multiple IPs Separate by comma and space

      We're going to use a subdomain to connect clients to.

      If using Dynu at this point for DDNS then create a DNS entry for the PiVPN server.

      Choose DDNS address.

      Confirm DDNS name choice.

      Enter password for "orangepi" user to backup configuration.

      Server Keys generation notification.

      Remember when I was talking about making sure UFW was installed and active? Immediately after the msg above, this will appear...

      UFW Configuration

      ** This is how UFW looks after completing the WireGuard installation process. If you don't enable it  prior to the installation, you'll experience errors at the browser level that mimic DNS issues. I address this at the end where you can make manual edits to get it working again. Or you could uninstall pivpn and UFW and start fresh. Editing the firewall will be easier once you see the issue.

      Unattended Upgrades Notification

      Enable Unattended Upgrades

      Enter password to enable unattended upgrades.

      Installation Complete

      Reboot Necessary

      Reboot Confirmation

      Adding Users to the WireGuard Server:

      1. Log back in as "orangepi".

      Notice now there's a virtual adapter for the WireGuard clients below the banner:

      Virtual Adapter -

      ifconfig output - Virtual Adapter - wg0

      Type "pivpn" to get a list of available commands.

      PiVPN Available Commands

      2. Type " pivpn -a" to begin adding a client.
      • Enter the user's name as the Client Name, i.e. " john.doe".
      The client's config file is generated and placed in " /home/orangepi/configs/".
      • To generate a QR Code for the mobile app run " pivpn -qr".

      Generate a new client config for each user!

      3. WinSCP into "/home/orangepi/configs/" and download config file to the client machine with the WireGuard client installed.

      WinSCP Retrieve User Config File:

      Remember you now need to feed WinSCP the private key before connecting!

      1. Open WinSCP and click on the word " Advanced..." not the drop down.

      2. Click on SSH --> Authentication.

      3. Browse for and select your private key file from earlier (rsa-key-orangepi.ppk).


      4. Click "OK" and login to your orangepi.

      5. Type in private key passphrase.

      6. Navigate to " /home/orangepi/configs/" and copy the client config ( john.doe.conf) to the client machine.

      Install WireGuard Client (Windows 7, 8.1, 10, 11, 2008R2, 2012R2, 2016, 2019, 2022):

      1. Download the client from (
      • MSI files are available here.
      This installation will cover v0.5.3 for Windows.

      2. Literally run "wireguard-installer.exe" and when the installation is done the main window will open.

      3. Click "Import tunnel(s) from file" and point it to  your config file. In this example we used "john.doe.conf".

      4. Click "Activate" to connect.

      *You can view the logs on the other tab to verify the handshake process has completed.
      *If you see handshake errors over and over again make sure the port is forwarded on the router.

      Managing Certificates on the WireGuard Server :

      List active client certificates:

      pivpn -l

      Add a client:

      pivpn -a

      Display the qrcode for a particular client (for mobile adding):

      pivpn -qr

      Remove a client:

      pivpn -r

      Disable a client but keep the certificate on the server:

      pivpn -off

      Enable a client that was previously disabled:

      pivpn -on

      View currently connected clients:

      pivpn -c

      Troubleshooting (if you didn't heed my warning about UFW):


      ** UFW (uncomplicated firewall) needs to be installed and enabled before running the script!  If not it'll mimic DNS issues at the browser level. Open Chrome, try to pull up a website, it'll hang. Pinging a website via FQDN or IP and it will work.

      If you didn't test while on prem you'll want to fix this ASAP before you forget about it. This can be done remotely.

      Each time the PI is rebooted (sudo reboot) you'll have to run "pivpn -d" to fix it before traffic is able to flow again. You'll receive an error about "Iptables MASQUERADE rule" not being set.

      *The issue is created when a route is missing from iptables that should have been created when running the script. Specifically a route from the tun0 adapter redirecting traffic to the ethernet adapter (end0 in this case) (end0 is eth0 on other machines). I haven't had a chance to investigate the script thoroughly but I suspect there's an issue with the "iptables-persistent" package based on lines 693 to 710 located here ""

      You can check and correct this by following below:

      *Assumes default ports and private ip ranges
      1. Run
        1. sudo ufw show added
          1. Check to see if the following lines exist:
            1. OpenVPN:
              1. ufw route allow in on tun0 out on end0 from
              2. ufw allow 1194/udp comment 'allow-openvpn'
            2. WireGuard:
              1. ufw route allow in on wg0 out on end0 from
              2. ufw allow 51820/udp comment 'allow-wireguard'
      If one or the other doesn't exist add them:
        1. OpenVPN:
          1. sudo ufw allow 1194/udp comment 'allow-openvpn'
          2. sudo ufw route allow in on tun0 out on end0 from
        2. WireGuard:
          1. sudo ufw allow 51820/udp comment 'allow-wireguard'
          2. sudo ufw route allow in on wg0 out on end0 from


      No comments: