newspaint

Documenting Problems That Were Difficult To Find The Answer To

Setting Up OpenVPN Server for Rooted LineageOS Phone

Installation Steps

Install OpenVPN Server

me@server:~$ sudo apt-get install openvpn
The following NEW packages will be installed:
  liblzo2-2 libpkcs11-helper1 openvpn
0 upgraded, 3 newly installed, 0 to remove and 0 not upgraded.
Need to get 513 kB of archives.
After this operation, 1,353 kB of additional disk space will be used.
me@server:~$ sudo apt-get install openssl
The following NEW packages will be installed:
  openssl
0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
Need to get 492 kB of archives.
After this operation, 956 kB of additional disk space will be used.

Choose a routed VPN (rather than a bridged). Use username/password authentication (still requires server certificate authority (CA) and server certificate.

Edit /etc/default/openvpn and add:

# Ensure tunnel device is available
if [ ! -d /dev/net ]; then
  mkdir /dev/net
fi

if [ -d /dev/net ]; then
  if [ ! -e /dev/net/tun ]; then
    mknod /dev/net/tun c 10 200
    chmod 666 /dev/net/tun
  fi
fi

Create a tunnel device:

me@server:~# openvpn --mktun --dev tun0

Create Certificate Authority

me@server:~# mkdir /etc/openvpn/ssl
me@server:~# cd /etc/openvpn/ssl
me@server:/etc/openvpn/ssl# openssl genrsa -out ca.key 2048
Generating RSA private key, 2048 bit long modulus
............+++
................................................................................................+++
e is 65537 (0x10001)
me@server:/etc/openvpn/ssl# openssl req -new -x509 -key ca.key -out ca.crt

Now we have ca.crt (the certificate authority certificate) and ca.key (the key for the certificate authority).

You can get the text form of the certificate (used later for the client configuration) by issuing the command:

me@server:/etc/openvpn/ssl# openssl x509 -in ca.crt -text

… and extracting the portion between (and including) the BEGIN CERTIFICATE and END CERTIFICATE lines.

Create Server Certificate and Sign Using Certificate Authority

me@server:/etc/openvpn/ssl# openssl genrsa -out signing.key 2048
Generating RSA private key, 2048 bit long modulus
.....+++
............................................................+++
e is 65537 (0x10001)
me@server:/etc/openvpn/ssl# openssl rsa -in signing.key -pubout -out signing.pub
writing RSA key
me@server:/etc/openvpn/ssl# openssl req -new -key signing.key -out request.csr

me@server:/etc/openvpn/ssl# openssl x509 -req -days 1500 -in request.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt
Signature ok
Getting CA Private Key
me@server:/etc/openvpn/ssl# openssl x509 -in server.crt -noout -text

Now we have server.crt (the server certificate).

Create Difie-Hellman Key

me@server:/etc/openvpn/ssl# openssl dhparam -out dh1024.pem 1024

Create Static Shared Key

me@server:/etc/openvpn/ssl# openvpn --genkey --secret static.key

Create auth.pl

(taken from the example at /usr/share/doc/openvpn/examples/sample-scripts/auth-pam.pl)

#!/usr/bin/perl -w

use strict;

# Allowed username/password combinations
my %users = (
    'jim' => 'letmein',
    'mary' => 'password123',
);

# Get username/password from file

my $ARG;
if ($ARG = shift @ARGV) {
    if (!open (UPFILE, "<$ARG")) {
        print "Could not open username/password file: $ARG\n";
        exit 1;
    }
} else {
    print "No username/password file specified on command line\n";
    exit 1;
}

my $username = <UPFILE>;
my $password = <UPFILE>;

if (!$username || !$password) {
    print "Username/password not found in file: $ARG\n";
    exit 1;
}

chomp $username;
chomp $password;

close (UPFILE);

if ( $users{$username} && ( $password eq $users{$username} ) ) {
    exit 0;
} else {
    print "Auth '$username' failed.\n";
    exit 1;
}

Create server.conf

tls-server
port 1194
proto udp
dev tun
mssfix 576
cipher AES-256-CBC

ca /etc/openvpn/ssl/ca.crt
cert /etc/openvpn/ssl/server.crt
key /etc/openvpn/ssl/signing.key
dh /etc/openvpn/ssl/dh1024.pem

tls-auth /etc/openvpn/ssl/static.key 0

script-security 2 # necessary for auth-user-pass-verify
auth-user-pass-verify /etc/openvpn/auth.pl via-file
client-cert-not-required
username-as-common-name

server 10.44.12.0 255.255.255.0 # subnet for clients
keepalive 10 120
comp-lzo
persist-key
persist-tun
status /var/log/openvpn-status.log
log /var/log/openvpn.log
verb 3

push "redirect-gateway def1"
push "dhcp-option DNS 1.1.1.1" # cloudflare DNS

Enabling/Starting/Stopping OpenVPN

me@server:~# systemctl enable openvpn@server.service
me@server:~# systemctl start openvpn@server.service
me@server:~# systemctl stop openvpn@server.service

Create .ovpn Configuration File for OpenVPN Android Client

tls-client
remote 192.0.2.44 # the IP address of my OpenVPN server
port 1194
proto udp
comp-lzo
auth-user-pass
key-direction 1
mssfix 576
cipher AES-256-CBC

<ca>
-----BEGIN CERTIFICATE-----
...
...
...
-----END CERTIFICATE-----
</ca>

<tls-auth>
-----BEGIN OpenVPN Static key V1-----
...
...
...
-----END OpenVPN Static key V1-----
</tls-auth>

On The Phone

Install “OpenVPN Connect – Fast & Safe SSL VPN Client” by “OpenVPN”.

Then add .ovpn file created above.

Install iptables Scripts

me@server:~# apt-get install iptables-persistent
The following NEW packages will be installed:
  iptables iptables-persistent libnfnetlink0 netfilter-persistent
0 upgraded, 4 newly installed, 0 to remove and 0 not upgraded.
Need to get 292 kB of archives.
After this operation, 1,804 kB of additional disk space will be used.

Edit /etc/iptables/rules.v4:

###############################################################################
# iptables IPv4 rules for reload on start-up
#
# To Reload:
#   service netfilter-persistent restart
#
# To Test:
#   iptables-restore -t </etc/iptables/rules.v4
###############################################################################

*mangle
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
COMMIT

*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]

-A POSTROUTING -s 10.44.12.0/24 -o eth0 -j MASQUERADE

COMMIT

*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
COMMIT

Issues

external program fork failed

If you see something like the following:

Wed Jun 20 03:33:31 2018 192.0.2.41:39523 WARNING: External program may not be called unless '--script-security 2' or higher is enabled. See --help text or man page for detailed info.
Wed Jun 20 03:33:31 2018 192.0.2.41:39523 WARNING: Failed running command (--auth-user-pass-verify): external program fork failed

… then you probably have a “script-security 1” parameter somewhere in your configuration (after any other script-security 2 directives). Grep for it and comment it out so that your “script-security 2” directive can take effect.

See Also

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: