Professor
Professional
- Messages
- 773
- Reaction score
- 868
- Points
- 93
I noticed that the question about Raspberry Pi networking has become relevant. There is a lot of information on setting up an access point. In each of these guides, some steps contradict each other, so here are two methods that previously worked.
I hope they help someone.
As far as I know, this problem can be solved, but if there is a way to avoid it in the first place, then why not.
- Hostapd — A daemon that allows the board to act as an access point and authentication server.
- Dnsmasq — A lightweight and fast DNS, DHCP, and TFTP server used to provide domain names and related services to small networks.
- Dhcpcd — A DHCP client (supposedly installed by default, but I didn't have it).
Therefore, /etc/dhcpcd.confwe add the following line to the end of the file:
To do this, /etc/network/interfacesadd the setting to the file wlan0or change it, if it already exists, to the following:
Also, when testing the access point settings, I encountered a problem where Dnsmasq starts before the interface settings are applied, and because of this, the first launch occurs with an error.
This can be solved by adding a parameter Restartto [Service]the service file ( /lib/systemd/system/dnsmasq.service):
Also, for these settings to work, you need to add the path to them to the variable DAEMON_CONFin /etc/default/hostapd:
I assume you have the latest version of Raspbian OS installed, all default packages are up to date, and SSH access is configured. Let's proceed to installing additional software to build a VPN server.
Installing UPnP Client
Universal Plug-n-Play (UPnP) is a protocol for opening ports on your internet router so that applications can communicate with each other over the internet. We need this so Putty can communicate with your RPi after it's installed in a remote location, and so the OpenVPN client on your Windows and/or Android devices can use it.
The RPi VPN server we're building requires virtually no maintenance. However, you'll want to check it and update the software from time to time. SSH with Putty allows us to do all of this, and UPnP software ensures we can access our RPi from anywhere in the world.
MiniUPnP.
MiniUPnP is the easiest to install and the fastest to use. So, we'll install it initially. If you have any problems with MiniUPnP working with your router, you can refer to the next section of this article to install PortMapper, an alternative UPnP software package.
We execute the commands to install MiniUPnP and its Python module:
Answer "Y" to any prompts about additional disk space, etc. The first command installs upnpc from the command line for testing. The second command installs the Python Package Installer (PIP), which is used in the third command to install the layer used by the miniupnpc Python package in our script. Now let's test it. Enter the following:
Among all the garbage that is spat out, there should be a line that begins with:
However, if you don't see this, or instead find error messages such as “No IGD UPnP Device found on the network!”
Then MiniUPnP won't be able to connect to your router. This may be because UPnP isn't enabled on your router or MiniUPnP isn't compatible with your router. Consult your router's user manual to confirm that it supports UPnP and how to enable it.
If MiniUPnP doesn't work with your router and it supports UPnP, proceed to the next section, PortMapper (an alternative to MiniUPnP), to use it. Otherwise, we're done with this section.
PortMapper (alternative to MiniUPnP).
You're here because MiniUPnP can't connect to your router, even though it supports UPnP and is enabled. Don't worry, we have an alternative.
PortMapper is a Java application, so it requires more work to install. It also runs a little slower, but that shouldn't be a problem for us.
If you haven't already logged into your RPi using puTTY, do so now, set the user to root, and navigate to the "root" folder:
Now run the wget command to download PortMapper:
Or download the script from here: http://bitman.org/irafinch/rpi-vpn.zip
The command wget 'web-gets' PortMapper-1.9.5.jar renames it to just PortMapper.jar (this is much easier to work with).
Note: I have tested this ONLY with version 1.9.5 of PortMapper. There may be newer versions of this program (and some are alpha versions (untested)). Using any other version may not work and is not supported.
PortMapper requires the Java Runtime Environment (JRE), and depending on which Raspbian version you downloaded, it may not be installed. So, let's run the JRE installation command to ensure it's installed:
If it's already there, you'll see a message stating it's up-to-date. If not, you'll be prompted to install it along with the space requirements. Simply answer "Y."
We're performing a headless installation because we're only communicating with the RPi via SSH, not the graphical user interface (GUI), so we don't need all those extra components. However, it's a bit large and takes time to install.
Now let's test it and make sure it can communicate with your router. Enter this single line:
This will return about a dozen lines (if everything is working correctly). These should contain information such as your router's name, manufacturer, model, etc. If you don't see this information or see error messages instead, PortMapper is not compatible with your router.
I hope everything worked out for you, but you can ask questions in the comments.
Installing and configuring OpenVPN
For Wireless:
OpenVPN on Jessie doesn't work well with WiFi adapters. It disconnects the WiFi connection upon startup. So, if you're using your RPi wirelessly, we need to edit the following file first:
Edit the HOTPLUG_INTERFACES line so it looks like this:
Press Ctrl + X and Y to save and exit.
Note: The above ifplugd file does not apply to Raspberry Pi 3 models or Raspbian Stretch or Buster versions.
Since we prefer an Ethernet connection, let's move on. Now, run the following command on your Raspberry Pi:
Aha, now you have a working VPN server! But… The problem is, no one can talk to it or even knows how to talk to it. So we have a little more work to do. We need to generate some keys, both public and private, that will be used to connect to our RPi VPN server. We'll use RSA (Rivest-Shamir-Adleman) Cryptosystem. It's already built into OpenVPN, so all we need to do is tell OpenVPN to use it. Run the following command:
This copies the RSA software from the "examples" directory to the "etc" directory so we can make changes without messing up the original. Now we'll simply "change directory" to our working copy so we can work with it:
And let's make a working copy of the vars.example file:
At this point, there's no need to change any parameters in the vars file; the default values are fine for this setup. Now it's time to generate the CA (Certificate Authority) certificate and the root CA certificate. This is the first step in creating a key pair (server and client) for using our VPN server. So, follow these steps: Initialize the Public Key Infrastructure (PKI).
Public Key Infrastructure.
(PKI - Public Key Infrastructure) is a set of resources (technical, material, human, etc.), distributed services, and components used collectively to support cryptographic tasks based on private and public keys. PKI is based on the use of a public-key cryptographic system and several core principles:
This creates a structure for our master CA certificate and public/private key pairs (these keys are actually created for more than just structures):
Create our CA, enter:
You can choose not to use the "nopass" option, and you'll be prompted to enter a passphrase. You'll need this every time you connect to the OpenVPN server. However, if you don't disclose your certificate authority publicly, there's no need to password-protect it with a passphrase. Now you'll be prompted to enter a "Common name." I recommend using the Raspberry Pi hostname, if you've specified one, or a unique name for this server. If you create multiple Raspberry Pi VPN servers, this will make it easier to distinguish them from each other.
Note: Remember this shared name you entered! You'll need it later.
Now it's time to create the root CA certificate, so enter the following at the command prompt:
The Servername is exactly what you entered in the "Common Name" field. You haven't forgotten it yet, have you? You'll be prompted to enter the "Common Name" again, but it should default to the server name you entered, so just press Enter. Now we need to sign this server certificate so it can be used:
Where "servername" is, again, the server name you selected above. Then simply respond "yes" to the prompt.
Next, you need to create a Diffie-Hellman key exchange. This allows two computers to exchange secret keys without knowing who they are beforehand. Enter (this may take some time — like hours if you're using a 2048-bit key size — highly recommended):
Make some coffee (or watch a movie if you used a 2048-bit key size) and come back here when it's ready. Sometimes, if you're really lucky, it can happen quickly if it finds a matching pair of random prime keys early.
It took me about 40 minutes and the result is the following output:
Now we need to take additional security measures to prevent denial-of-service (DoS) attacks. We need to create a hash-based message authentication code (HMAC).
If the OpenVPN server sees a VPN request without this code, it will not even respond, which will prevent DoS attacks.
Just enter:
Next we need to create a server configuration file that tells OpenVPN how to run on this RPi.
Then copy the following into nano:
You need to change two lines. They are all marked "# TBD." Replace SERVERNAME with the name of your OpenVPN server (this is Case Sensitive!). Press Ctrl + X and Y to save and exit.
Note: Don't worry about the unusual IP addresses 111.111.111.111 and 222.222.222.222, a small script in the next chapter will set it all up.
Almost done. The next step is setting up the server configuration file that allows OpenVPN to send and receive data (packet forwarding). By default, Raspbian blocks all of this.
Let's uncomment the following line:
Press Ctrl + X and Y to save and exit. Then enter this to apply the change:
Next, we need to open up Raspbian's firewall a bit to allow OpenVPN to communicate with the outside world. To do this, we need to create a new file.
We insert the following lines:
We've just created a Bash script, and we need to make it executable and configure it to run every time our RPi boots.
So, enter these 2 commands to make it executable and set the owner to "root":
I hope they help someone.
Setting up Raspberry Pi as a wireless access point
Installing Raspberry OS
I'd like to immediately emphasize that the system must be installed via BalenaEtcher, not via Raspberry Pi Imager. Otherwise, you'll run into problems when setting up the network adapter, which will simply block rfkill.
Code:
Wi-Fi is currently blocked by rfkill.
Use raspi-config to set the country before use.
As far as I know, this problem can be solved, but if there is a way to avoid it in the first place, then why not.
Step 1. Installing utilities
First, let's install all the basic utilities:- Hostapd — A daemon that allows the board to act as an access point and authentication server.
- Dnsmasq — A lightweight and fast DNS, DHCP, and TFTP server used to provide domain names and related services to small networks.
- Dhcpcd — A DHCP client (supposedly installed by default, but I didn't have it).
Code:
sudo apt install hostapd dnsmasq dhcpcd
Step 2. Configuring DHCP
For the access point to work, you need to completely dedicate the wireless interface and ensure that no other service interferes with its operation, including DHCP itself.Therefore, /etc/dhcpcd.confwe add the following line to the end of the file:
Code:
denyinterfaces wlan0
Step 3. Configuring the interface
Now let's move on to setting up the wireless interface itself. It must have a static IP address, otherwise other devices will not be able to find it when they try to connect.To do this, /etc/network/interfacesadd the setting to the file wlan0or change it, if it already exists, to the following:
Code:
allow-hotplug wlan0
iface wlan0 inet static
wireless-mode Master
address 192.168.52.1
netmask 255.255.255.0
network 192.168.52.0
broadcast 192.168.52.255
# wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf
Step 4. Configuring the DNS server
For normal functioning of the DNS server, you can use the following configuration, which must be placed in /etc/dnsmasq.conf:
Code:
interface=wlan0
listen-address=192.168.52.1
bind-interfaces
server=8.8.8.8
domain-needed
bogus-priv
dhcp-range=192.168.52.5,192.168.52.250,12h
Also, when testing the access point settings, I encountered a problem where Dnsmasq starts before the interface settings are applied, and because of this, the first launch occurs with an error.
This can be solved by adding a parameter Restartto [Service]the service file ( /lib/systemd/system/dnsmasq.service):
Code:
Restart=always
RestartSec=5s
Step 5. Configuring hostapd
In the hostapd settings (/etc/hostapd/hostapd.conf), you need to specify the access point parameters, its security parameters, and name:
Code:
interface=wlan0
ssid=[Network name]
hw_mode=g
channel=6
macaddr_acl=0
auth_algs=1
ignore_broadcast_ssid=0
wpa=2
wpa_key_mgmt=WPA-PSK
wpa_passphrase=[Network password]
rsn_pairwise=CCMP
Also, for these settings to work, you need to add the path to them to the variable DAEMON_CONFin /etc/default/hostapd:
Code:
DAEMON_CONF="/etc/hostapd/hostapd.conf"
Step 6. Activating Services
The last step is to enable all the necessary services:
Code:
sudo systemctl enable hostapd
sudo systemctl start hostapd sudo systemctl enable dnsmasq
sudo systemctl start dnsmasq
Conclusion
At this point, the point setup is complete, and you can test it by connecting via SSH or, as in my case, by trying to access the web server that was set up:
Smart VPN Server on Raspberry Pi: Installation and Configuration
I assume you have the latest version of Raspbian OS installed, all default packages are up to date, and SSH access is configured. Let's proceed to installing additional software to build a VPN server.
Installing UPnP Client
Universal Plug-n-Play (UPnP) is a protocol for opening ports on your internet router so that applications can communicate with each other over the internet. We need this so Putty can communicate with your RPi after it's installed in a remote location, and so the OpenVPN client on your Windows and/or Android devices can use it.
The RPi VPN server we're building requires virtually no maintenance. However, you'll want to check it and update the software from time to time. SSH with Putty allows us to do all of this, and UPnP software ensures we can access our RPi from anywhere in the world.
MiniUPnP.
MiniUPnP is the easiest to install and the fastest to use. So, we'll install it initially. If you have any problems with MiniUPnP working with your router, you can refer to the next section of this article to install PortMapper, an alternative UPnP software package.
We execute the commands to install MiniUPnP and its Python module:
Code:
apt install miniupnpc
apt install python-pip
pip install miniupnpc
Answer "Y" to any prompts about additional disk space, etc. The first command installs upnpc from the command line for testing. The second command installs the Python Package Installer (PIP), which is used in the third command to install the layer used by the miniupnpc Python package in our script. Now let's test it. Enter the following:
Code:
upnpc -s
Among all the garbage that is spat out, there should be a line that begins with:
Code:
Found valid IGD

However, if you don't see this, or instead find error messages such as “No IGD UPnP Device found on the network!”
Then MiniUPnP won't be able to connect to your router. This may be because UPnP isn't enabled on your router or MiniUPnP isn't compatible with your router. Consult your router's user manual to confirm that it supports UPnP and how to enable it.
If MiniUPnP doesn't work with your router and it supports UPnP, proceed to the next section, PortMapper (an alternative to MiniUPnP), to use it. Otherwise, we're done with this section.
PortMapper (alternative to MiniUPnP).
You're here because MiniUPnP can't connect to your router, even though it supports UPnP and is enabled. Don't worry, we have an alternative.
PortMapper is a Java application, so it requires more work to install. It also runs a little slower, but that shouldn't be a problem for us.
If you haven't already logged into your RPi using puTTY, do so now, set the user to root, and navigate to the "root" folder:
Code:
sudo -s
cd /root
Now run the wget command to download PortMapper:
Code:
wget -O PortMapper.jar https://downloads.sourceforge.net/project/upnp-portmapper/PortMapper-1.9.5.jar
Or download the script from here: http://bitman.org/irafinch/rpi-vpn.zip
The command wget 'web-gets' PortMapper-1.9.5.jar renames it to just PortMapper.jar (this is much easier to work with).
Note: I have tested this ONLY with version 1.9.5 of PortMapper. There may be newer versions of this program (and some are alpha versions (untested)). Using any other version may not work and is not supported.
PortMapper requires the Java Runtime Environment (JRE), and depending on which Raspbian version you downloaded, it may not be installed. So, let's run the JRE installation command to ensure it's installed:
Code:
apt-get install default-jre-headless
If it's already there, you'll see a message stating it's up-to-date. If not, you'll be prompted to install it along with the space requirements. Simply answer "Y."
We're performing a headless installation because we're only communicating with the RPi via SSH, not the graphical user interface (GUI), so we don't need all those extra components. However, it's a bit large and takes time to install.
Now let's test it and make sure it can communicate with your router. Enter this single line:
Code:
java -jar PortMapper.jar -s | grep 'Router Info:'
This will return about a dozen lines (if everything is working correctly). These should contain information such as your router's name, manufacturer, model, etc. If you don't see this information or see error messages instead, PortMapper is not compatible with your router.
I hope everything worked out for you, but you can ask questions in the comments.
Installing and configuring OpenVPN
For Wireless:
OpenVPN on Jessie doesn't work well with WiFi adapters. It disconnects the WiFi connection upon startup. So, if you're using your RPi wirelessly, we need to edit the following file first:
Code:
nano /etc/default/ifplugd
Edit the HOTPLUG_INTERFACES line so it looks like this:
Code:
HOTPLUG_INTERFACES="eth0 wlan0 "
Press Ctrl + X and Y to save and exit.
Note: The above ifplugd file does not apply to Raspberry Pi 3 models or Raspbian Stretch or Buster versions.
Since we prefer an Ethernet connection, let's move on. Now, run the following command on your Raspberry Pi:
Code:
apt install openvpn
Aha, now you have a working VPN server! But… The problem is, no one can talk to it or even knows how to talk to it. So we have a little more work to do. We need to generate some keys, both public and private, that will be used to connect to our RPi VPN server. We'll use RSA (Rivest-Shamir-Adleman) Cryptosystem. It's already built into OpenVPN, so all we need to do is tell OpenVPN to use it. Run the following command:
Code:
cp -r /usr/share/easy-rsa /etc/openvpn/easy-rsa
This copies the RSA software from the "examples" directory to the "etc" directory so we can make changes without messing up the original. Now we'll simply "change directory" to our working copy so we can work with it:
Code:
cd /etc/openvpn/easy-rsa
And let's make a working copy of the vars.example file:
Code:
cp vars.example vars
At this point, there's no need to change any parameters in the vars file; the default values are fine for this setup. Now it's time to generate the CA (Certificate Authority) certificate and the root CA certificate. This is the first step in creating a key pair (server and client) for using our VPN server. So, follow these steps: Initialize the Public Key Infrastructure (PKI).
Public Key Infrastructure.
(PKI - Public Key Infrastructure) is a set of resources (technical, material, human, etc.), distributed services, and components used collectively to support cryptographic tasks based on private and public keys. PKI is based on the use of a public-key cryptographic system and several core principles:
- A private key is known only to its owner;
- The certification authority creates an electronic document - a public key certificate, thus certifying the fact that the private (secret) key is known exclusively to the owner of this certificate, the public key is freely transmitted in the certificate;
- Nobody trusts each other, but everyone trusts the certification authority;
- The certification authority confirms or denies that a public key belongs to a given person who owns the corresponding private key.
This creates a structure for our master CA certificate and public/private key pairs (these keys are actually created for more than just structures):
Code:
./easyrsa init-pki
Create our CA, enter:
Code:
./easyrsa build-ca nopass
You can choose not to use the "nopass" option, and you'll be prompted to enter a passphrase. You'll need this every time you connect to the OpenVPN server. However, if you don't disclose your certificate authority publicly, there's no need to password-protect it with a passphrase. Now you'll be prompted to enter a "Common name." I recommend using the Raspberry Pi hostname, if you've specified one, or a unique name for this server. If you create multiple Raspberry Pi VPN servers, this will make it easier to distinguish them from each other.
Note: Remember this shared name you entered! You'll need it later.
Now it's time to create the root CA certificate, so enter the following at the command prompt:
Code:
./easyrsa gen-req servername nopass
The Servername is exactly what you entered in the "Common Name" field. You haven't forgotten it yet, have you? You'll be prompted to enter the "Common Name" again, but it should default to the server name you entered, so just press Enter. Now we need to sign this server certificate so it can be used:
Code:
./easyrsa sign-req server servername

Where "servername" is, again, the server name you selected above. Then simply respond "yes" to the prompt.
Next, you need to create a Diffie-Hellman key exchange. This allows two computers to exchange secret keys without knowing who they are beforehand. Enter (this may take some time — like hours if you're using a 2048-bit key size — highly recommended):
- The Diffie–Hellman protocol (DH) is a cryptographic protocol that allows two or more parties to obtain a shared secret key over an unsecured communication channel. The resulting key is used to encrypt subsequent communications using symmetric encryption algorithms.
- The public key distribution scheme proposed by Diffie and Hellman revolutionized the world of encryption because it solved the main problem of classical cryptography—the problem of key distribution.
- In its pure form, the Diffie–Hellman algorithm is vulnerable to data modification in the communication channel, including the Man-in-the-Middle attack, so schemes using it employ additional one-way or two-way authentication methods.
Code:
./easyrsa gen-dh

Make some coffee (or watch a movie if you used a 2048-bit key size) and come back here when it's ready. Sometimes, if you're really lucky, it can happen quickly if it finds a matching pair of random prime keys early.
It took me about 40 minutes and the result is the following output:

Now we need to take additional security measures to prevent denial-of-service (DoS) attacks. We need to create a hash-based message authentication code (HMAC).
If the OpenVPN server sees a VPN request without this code, it will not even respond, which will prevent DoS attacks.
Just enter:
Code:
openvpn --genkey --secret pki/ta.key

Next we need to create a server configuration file that tells OpenVPN how to run on this RPi.
Code:
nano /etc/openvpn/server/server.conf
Then copy the following into nano:
Code:
# local 111.111.111.111
dev tun
proto udp
port 1194
ca /etc/openvpn/easy-rsa/pki/ca.crt
cert /etc/openvpn/easy-rsa/pki/issued/SERVERNAME.crt # TBD - Change SERVERNAME to your Server name
key /etc/openvpn/easy-rsa/pki/private/SERVERNAME.key # TBD - Change SERVERNAME to your Server name
dh /etc/openvpn/easy-rsa/pki/dh.pem
server 10.8.0.0 255.255.255.0
ifconfig 10.8.0.1 10.8.0.2
push "route 10.8.0.1 255.255.255.255"
push "route 10.8.0.0 255.255.255.0"
push "route 111.111.111.111 255.255.255.0"
push "dhcp-option DNS 222.222.222.222"
push "redirect-gateway def1"
client-to-client
duplicate-cn
keepalive 10 120
tls-auth /etc/openvpn/easy-rsa/pki/ta.key 0
compress lzo
persist-key
persist-tun
user nobody
group nogroup
cipher AES-128-CBC
log /var/log/openvpn.log
status /var/log/openvpn-status.log 20
verb 1
You need to change two lines. They are all marked "# TBD." Replace SERVERNAME with the name of your OpenVPN server (this is Case Sensitive!). Press Ctrl + X and Y to save and exit.
Note: Don't worry about the unusual IP addresses 111.111.111.111 and 222.222.222.222, a small script in the next chapter will set it all up.
Almost done. The next step is setting up the server configuration file that allows OpenVPN to send and receive data (packet forwarding). By default, Raspbian blocks all of this.
Code:
nano /etc/sysctl.conf
Let's uncomment the following line:
Code:
net.ipv4.ip_forward=1

Press Ctrl + X and Y to save and exit. Then enter this to apply the change:
Code:
sysctl -p
Next, we need to open up Raspbian's firewall a bit to allow OpenVPN to communicate with the outside world. To do this, we need to create a new file.
Code:
nano /root/open_vpn_firewall.sh
We insert the following lines:
Code:
#!/bin/sh
sleep 30
Adapter=`ip -o link show | awk '{print $2,$9}' | grep 'UP'| awk -F: '{print $1}'`
if [ -z "$Adapter" ]
then
Adapter='eth0'
fi
echo "Adapter = |$Adapter|"
/sbin/iptables -t nat -A POSTROUTING -o $Adapter -j MASQUERADE
/sbin/iptables -A FORWARD -i $Adapter -o tun0 -m state --state RELATED,ESTABLISHED -j ACCEPT
/sbin/iptables -A FORWARD -i tun0 -o $Adapter -j ACCEPT

We've just created a Bash script, and we need to make it executable and configure it to run every time our RPi boots.
So, enter these 2 commands to make it executable and set the owner to "root":
Code:
chmod 700 /root/open_vpn_firewall.sh
chown root /root/open_vpn_firewall.sh