Setup personal VPN service on Linux Debian 9 Stretch

Please, attention! Article currently in progress, but you can leave your comments if errors found.

Who need VPN?

Virtual Private Network (VPN) can be useful in many situations in a daily internet use.

For example you left New Zealand and can’t access some services as they are locked to your IP address region. With VPN you can still use these services (such as Steam or PlayStation Network, etc) as if you’ve still been located in New Zealand, no matter in which country you’re currently located.

Another example is when web site block access for some countries using GeoIP mod (Apache’s web server mod). It’s common in Israel to avoid hacker attempts (often means automatic bruteforce attacks) and haters comments and other countries such as Russia, where government block access up to 20 billions IP addresses to block Telegram messenger use, which cause thousands of services (including Google, Microsoft, Sony and other) to completely stop working.

Of course some companies need VPN to communicate between offices and remote personal from different locations in one Private Network for security reasons. But this guide not recommended for company’s VPN setup, as it lack of security.


Find your server’s IP address

To view your network interfaces type commands

ip a



ip a linux output

IP address is

In case you can’t figure out where is your public (external) IP address install tool host

apt install host

And enter


Your output should be like

root@72466d1ad2:~# host
Using domain server:
Aliases: has address

Can’t find eth0 interface?

If you noticed, out interface name is venet0 instead of eth0 what you can find in some other tutorials. That’s because our VPS (Virtual Private Server) is based on OpenVZ Virtualization and not on KVM. If you have eth0 interface, keep that in mind when configuring next firewall rules and other configurations.


Configuring iptables rules for VPN (optional)

Attention! This step is OPTIONAL, you can skip it and configure easier way with UFW (Uncomplicated Firewall, it’s like a front-end to iptables).

Let’s create a file with rules set for iptables, so we can easily import them at once. Edit file with any favorite text editor (vim or nano) and save it anywhere you want.
Before we begin, flush all existing rules in iptables:

iptables -F && iptables -X

To view your current rules list enter:

iptables -L

Output show us a clean rules set:

root@72466d1ad2:~# iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

Create a file (anywhere):

nano /etc/iptables.vpn.ipv4.rules

Start your IPv4 rules set by writing *filter at the beginning and COMMIT at the end of file.


#Allows all loopback traffic and drop all traffic to 127/8
-A INPUT -i lo -j ACCEPT
-A INPUT ! -i lo -s -j REJECT

#Allow ping
-A INPUT -p icmp -m state --state NEW --icmp-type 8 -j ACCEPT
-A INPUT -p icmp -m state --state ESTABLISHED,RELATED -j ACCEPT
-A OUTPUT -p icmp -j ACCEPT

#Allow SSH (if you use other port then 22 to connect to your server, don't forget to change it)
-A INPUT -i venet0 -p tcp -m state --state NEW,ESTABLISHED --dport 22 -j ACCEPT
-A OUTPUT -o venet0 -p tcp -m state --state ESTABLISHED --sport 22 -j ACCEPT

#Allow OpenVPN
-A INPUT -i venet0 -p udp -m state --state NEW,ESTABLISHED --dport 1194 -j ACCEPT
-A OUTPUT -o venet0 -p udp -m state --state ESTABLISHED --sport 1194 -j ACCEPT

#Allow DNS
-A INPUT -i venet0 -p udp -m state --state ESTABLISHED --sport 53 -j ACCEPT
-A OUTPUT -o venet0 -p udp -m state --state NEW,ESTABLISHED --dport 53 -j ACCEPT
-A INPUT -i venet0 -p tcp -m state --state ESTABLISHED --sport 53 -j ACCEPT
-A OUTPUT -o venet0 -p tcp -m state --state NEW,ESTABLISHED --dport 53 -j ACCEPT

#Allows HTTP and HTTPS connections
-A INPUT -i venet0 -p tcp -m state --state ESTABLISHED --sport 80 -j ACCEPT
-A INPUT -i venet0 -p tcp -m state --state ESTABLISHED --sport 443 -j ACCEPT
-A OUTPUT -o venet0 -p tcp -m state --state NEW,ESTABLISHED --dport 80 -j ACCEPT
-A OUTPUT -o venet0 -p tcp -m state --state NEW,ESTABLISHED --dport 443 -j ACCEPT

#Allow NTP
-A INPUT -i venet0 -p udp -m state --state ESTABLISHED --sport 123 -j ACCEPT
-A OUTPUT -o venet0 -p udp -m state --state NEW,ESTABLISHED --dport 123 -j ACCEPT

#Allow using TUN to tunnel through the VPN, adjust if you're using TAP
-A INPUT -i tun0 -j ACCEPT
-A FORWARD -i tun0 -j ACCEPT
-A OUTPUT -o tun0 -j ACCEPT

#Allow forwarding your traffic, adjust your TUN (TAP) to physical interface 
-A FORWARD -i tun0 -o venet0 -s -j ACCEPT

#log iptables denied calls
-A INPUT -m limit --limit 3/min -j LOG --log-prefix "iptables_INPUT_denied: " --log-level 4
-A FORWARD -m limit --limit 3/min -j LOG --log-prefix "iptables_FORWARD_denied: " --log-level 4
-A OUTPUT -m limit --limit 3/min -j LOG --log-prefix "iptables_OUTPUT_denied: " --log-level 4

#Block all other inbound and outbound traffic


Now create another file for IPv6 rules. All rules for IPv6 is blocking all traffic for security reasons (in case you don’t actually use IPv6)

nano /etc/iptables.vpn.ipv6.rules




The other rule should be entered manually into separated table to masquerade traffic from VPN

iptables -t nat -A POSTROUTING -s -o venet0 -j MASQUERADE

Now, import rules, we’ve created to iptables:

iptables-restore < /etc/iptables.vpn.ipv4.rules 
ip6tables-restore < /etc/iptables.vpn.ipv6.rules

To save your rules and load them automatically you can install debian package iptables-persistent

apt install iptables-persistent

Installation process will guide you to save your current configuration, but in future you can run this command to save the changes:

service netfilter-persistent save

Last changes in network configuration has to be made

Open file


And uncomment the line net.ipv4.ip_forward=1 ​​to enable packet forwarding for IPv4

also open /etc/hosts and comment all ipv6 addresses.
In our example result is:

#ff02::1                ip6-allnodes
#ff02::2                ip6-allrouters localhost.localdomain localhost
# Auto-generated hostname. Please do not remove this comment. 72466d1ad2
#::1            localhost ip6-localhost ip6-loopback


Configuring UFW for VPN


Leave a Reply