Creating an OpenVPN client for bridging traffic between two networks.

This is going to be somewhat backwards, I will follow this up with a creating an OpenVPN server post at a later time.


Be aware that this client will be setup in AWS so there will be AWS references in the article. This can be easily translated to your own network.

A prerequisite for this is a OpenVPN server at a remote location that is not in AWS, your office for example.
Spin up an ami, preferably CentOS you can use the Amazon Linux AMI as well as it is built from the same meat and potatoes.
I used an ami with the ID of ami-033e6106180a626d0 this is a CentOS linux ami.
Make sure your instance has an elastic IP and it can be reached externally via SSH.
Always work with sudo, I use the sudo -i command to accomplish this.

*Note the service on the OpenVPN client is called openvpn-client@aws.service

 

Configure your OpenVPN server for the Client

You will need to do two things, assign the client a static IP when it connects to the VPN,
and advertise the subnets that sit behind the VPN client.
SSH into your Server instance.
Work as sudo, create a CCD directory, and a client file.

sudo -i
mkdir /etc/openvpn/ccd
cd /etc/openvpn/ccd
touch myuser

Edit the myuser file and add the following.

ifconfig-push 10.8.1.254 255.255.255.0
iroute 172.31.1.0 255.255.255.0
push "route 172.31.1.0 255.255.255.0 10.8.1.254"
push "redirect-gateway def1"
route 172.31.1.0 255.255.255.0 10.8.1.254

*Note that the file name myuser in this directory should reflect the user id that the AWS client will connect with and it should be unique.

This OpenVPN server configuration uses only one set of certificate files, but I created a unique LDAP user ID called myuser

that only this server connects with. This is defined by the server configuration line username-as-common-name each time an LDAP user connects

instead of the certificate name it will be identified as the LDAP user ID.

As such anytime myuser connects it is assigned a static IP of 10.8.1.254 as defined by the ifcongif-push line as defined in the myuser file.

The iroute 172.31.1.0 255.255.255.0 advertises the AWS subnet that sits behind the AWS client. 

You also don’t need the last 3 lines, especially push “redirect-gateway def1” only add that if you want to redirect all gateway traffic from AWS via the VPN. The other 2 are redundant as those routes are pushed and advertised via iroute and the entries below so either or. Navigate to the open vpn directory /etc/openvpn and edit the server.conf file and add the following.

push "route 172.31.1.0 255.255.255.0"
client-config-dir ccd
route 172.31.1.0 255.255.255.0
route 10.8.1.254 255.255.255.0

The above advertises the new route to all the clients that connect and tells the clients the configuration directory is ccd.

ipp.txt does not work for pushing static IPs as such we use the ccd directory here.

route 172.31…in this file in conjunction with the iroute 172 in the myuser file direct all traffic to said client.

route 10.8…in this file in conjunction with ifconfig-push 10.8 in the myuser file assign a static IP to the myuser client.

 

Install and configure OpenVPN on the client.

Use your key and remote into the client Linux instance. Work with sudo

sudo -i

Update your instance

yum update -y 

Install enterprise linux repository (EPEL)

yum install epel-release -y

Update your repository again

yum update -y

Install open vpn and wget

yum install -y openvpn

Create a client directory in the OpenVPN directory and move into it.

mkdir /etc/openvpn/client
cd /etc/openvpn/client

Create two configuration files.

touch aws.conf
touch login.conf

Edit the login.conf with your user id and password. First line is the user id and the second line is your OPEN VPN password.

nano login.conf

The file should look like this.

myuser
MyP@sswerd$

Save and exit the file.

Edit the aws.conf file using nano.

The file should look something like this.

client
dev tun
cipher AES-256-CBC
tls-client
tls-auth ta.key 1
remote-cert-tls server
auth-user-pass /etc/openvpn/client/login.conf
keepalive 10 60
proto udp
remote vpn.mydomain.com 1194 udp
topology subnet
pull
persist-tun
persist-key
user nobody
group nobody
verb 3
<ca>
-----BEGIN CERTIFICATE-----
-----END CERTIFICATE-----
</ca>
<cert>
-----BEGIN CERTIFICATE-----

-----END CERTIFICATE-----
</cert>
<key>

-----BEGIN PRIVATE KEY-----
-----END PRIVATE KEY-----

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

Obviously add your own certificates to the aws.configuration file. Save the file and exit.

I include my certificates in the configuration file.

You don’t have to, you can move them somewhere else and reference them in the configuration file.

Also note that aws.conf will be the name of the service, you can name the file whatever you would like but then you have to reflect this in the configuration of the service.

 

IP Forwarding on the Client

Next you need to configure IP forwarding on the client as you do on the Server. Without this the bridging will not work.

First check and make sure your firewall is disabled on the AMI, generally they are by default.

systemctl status firewalld

If it’s disabled, move on, otherwise do the follwing.

systemctl stop firewalld
systemctl disable firewalld

Next enable IP forwarding.

nano /etc/sysctl.conf

Add the following line to the conf file.

net.ipv4.ip_forward = 1

Restart the network service.

systemctl restart network

Test your open vpn connection. If it is working disconnect and move on to the next step.

openvpn --config aws.conf

 

Create an OpenVPN service on the Client.

Next you will create an open VPN service which will restart and reconnect if it crashes.

Last thing you want is the tunnel crashing and not coming back up.

Create the service.

systemctl ebnable openvpn-client@aws.service

Note that the client portion between the openvpn and @ symobol is the client directory we created earlier, and the aws after the @ is the aws.conf file we created.

This will create the service.

Next start the service and check the status.

systemctl start openvpn-client@aws.service
systemctl status openvpn-client@aws.service

The status should spit out the following.

● openvpn-client@aws.service - OpenVPN tunnel for aws
Loaded: loaded (/usr/lib/systemd/system/openvpn-client@.service; enabled; vendor preset: disabled)
Active: active (running) since Thu 2019-06-06 17:03:54 UTC; 1h 7min ago
Docs: man:openvpn(8)
https://community.openvpn.net/openvpn/wiki/Openvpn24ManPage
https://community.openvpn.net/openvpn/wiki/HOWTO
Main PID: 4209 (openvpn)
Status: "Initialization Sequence Completed"
CGroup: /system.slice/system-openvpn\x2dclient.slice/openvpn-client@aws.service
└─4209 /usr/sbin/openvpn --suppress-timestamps --nobind --config aws.conf

Jun 06 18:03:54 ip-172-31-1-81.ca-central-1.compute.internal openvpn[4209]: TLS: soft reset sec=0 bytes=82353/-1 pkts=1140/0
Jun 06 18:03:54 ip-172-31-1-81.ca-central-1.compute.internal openvpn[4209]: VERIFY OK: depth=1, C=CA, ST=AB, L=Edmonton, O=Some Company, OU=IT, CN=domain.com, name=server, emailAddress=admin@domain.com
Jun 06 18:03:54 ip-172-31-1-81.ca-central-1.compute.internal openvpn[4209]: VERIFY KU OK
Jun 06 18:03:54 ip-172-31-1-81.ca-central-1.compute.internal openvpn[4209]: Validating certificate extended key usage
Jun 06 18:03:54 ip-172-31-1-81.ca-central-1.compute.internal openvpn[4209]: ++ Certificate has EKU (str) TLS Web Server Authentication, expects TLS Web Server Authentication
Jun 06 18:03:54 ip-172-31-1-81.ca-central-1.compute.internal openvpn[4209]: VERIFY EKU OK
Jun 06 18:03:54 ip-172-31-1-81.ca-central-1.compute.internal openvpn[4209]: VERIFY OK: depth=0, C=CA, ST=AB, L=Edmonton, O=Some Company, OU=IT, CN=domain.com, name=server, emailAddress=admin@domain.com
Jun 06 18:03:54 ip-172-31-1-81.ca-central-1.compute.internal openvpn[4209]: Outgoing Data Channel: Cipher 'AES-256-GCM' initialized with 256 bit key
Jun 06 18:03:54 ip-172-31-1-81.ca-central-1.compute.internal openvpn[4209]: Incoming Data Channel: Cipher 'AES-256-GCM' initialized with 256 bit key
Jun 06 18:03:54 ip-172-31-1-81.ca-central-1.compute.internal openvpn[4209]: Control Channel: TLSv1.2, cipher TLSv1/SSLv3 ECDHE-RSA-AES256-GCM-SHA384, 4096 bit RSA

Now we need to make sure that this service starts automatically when the server reboots or the tunnel crashes.

Check to see if the service is enabled to auto start.

systemctl is-enabled openvpn-client@aws.service

If you get the following that means the service will auto start.

[root@ip-172-31-1-81 /]# systemctl is-enabled openvpn-client@aws.service

enabled

Otherwise do the following.

Open the openvpn service.

nano /etc/systemd/system/multi-user.target.wants/openvpn-client\@aws.service

Under the [Service] heading add the line Restart=always

[Unit]

....

[Service]

...

Restart=always

[Install]

...

Test the service to see if it restarts by either rebooting the AMI or do the following.

Check the PID of the process, kill it, and see if it restarts.

systemctl status openvpn-client@aws.service

Should see something along the lines of….

Main PID: 4209 (openvpn)

Kill the process to see if it restarts

kill -9 4209

If you do a status again the process should have a new PID.

 

That’s it, now don’t forget to add your routes to the Networking side of things. Your gateway on the Server side needs to know how to get to the AWS client and it’s networks.

If you are putting this in AWS, rememeber to add the routes in the Route table and make changes to the security group as well. Traffic needs to flow both ways.

 

AWS Route Table Changes

In AWS find the VPN that the AWS client lives in and locate the route table for said Subnet.

In this case its called OpenVPN_RT

Click on this route table. 

Then Edit the route.

 

Click Add route… then type in the CIDR block of the Network in your remote location, the network that sits behind the VPN server.Select instance and select the AWS Client VPN instance that you have created.

This will translate the route to the instances Network Interface once you click save routes.

Do the same for the VPN CIDR and any other CIDRs that live behind the VPN Server.

 

Your security group should look like this.

Note the SSH entries, they were added in order to initially setup the linux boxes.

If your traffic is routing properly you can remove these last two entries as these are no longer needed and you can reach the AMIs via the AWS subnet IP.

Ignore the MKT VPC entry this is used for a peering connection.

PROFIT!

 

Resources:

https://www.digitalocean.com/community/tutorials/how-to-set-up-and-configure-an-openvpn-server-on-centos-7

https://www.digitalocean.com/community/tutorials/how-to-configure-a-linux-service-to-start-automatically-after-a-crash-or-reboot-part-1-practical-examples

How to Generalize a Linux VM Template

When building out an environment of any kind, you need to have a good starting base, a strong foundation and the same holds true for many things. It’s no different when building a virtual machine (VM) template to deploy in your environment in a repeatable fashion.

Recently I spent some time developing a generalized/sanitized VM template for Red Hat Enterprise Linux (RHEL) versions 6 and 7. This script should be run right before you shutdown the VM and template it for reuse.

#!/bin/bash
echo "Generalize the template..."
echo "Remove RHN system ID..."
rm -f /etc/sysconfig/rhn/systemid

echo "Create sanitized ifcfg-eth0..."
echo -en 'DEVICE=eth0\nTYPE=Ethernet\nONBOOT=yes\nBOOTPROTO=dhcp\n' > /etc/sysconfig/network-scripts/ifcfg-eth0

echo "Clear /etc/sysconfig/network file..."
cat > /etc/sysconfig/network < /dev/null

echo "Remove SHH keys..."
rm -f /etc/ssh/ssh_host_*

echo "Remove udev rules..."
rm -f /etc/udev/rules.d/70-*

echo "Remove fixed hostname..."
rm -f /etc/hostname

echo "Clear Machine ID (SID)..."
> /etc/machine-id

echo "Remove all logs from /var/log..."
rm -rf /var/log/*

echo "Remove all logs from /root..."
rm -rf /root/*

Debian 8 Jessie sources.list, missing installation sources.

debian8_with_release_date

Each time I install Debian Jessie or Debian 8 I notice that I can not install any software packages afterwards. I’m not sure if it is me, or the installation media, but the sources.list is missing entries. Recently I tried installing xrdp, which allows Windows OS machines to RDP into Linux OS machines.

Commands such as…

apt-get update
apt-get upgrade
apt-get install package_name

… yielded no results. When I navigate to /etc/apt/sources.list I noticed there were only 3 entries in the file.

deb cdrom:[Debian GNU/Linux....

deb http://security.debian.org/ jessie/updates main contrib
deb-src http://security.debian.org/ jessie/updates main contrib

However the Debian Wiki specifies two additional sources.

deb http://httpredir.debian.org/debian jessie main
deb-src http://httpredir.debian.org/debian jessie main

deb http://httpredir.debian.org/debian jessie-updates main
deb-src http://httpredir.debian.org/debian jessie-updates main

Once you add these to your sources list and run the above commands the
packages should update, and you can proceed with installing XRDP.

Install and Configure OpenVPN on OSMC/Kodi

Let’s face it, Kodi is pretty popular right now, everyone is talking about it. One of the first things I did after I installed OSMC on my Raspberry Pi was to configure OpenVPN. There is a little bit of work involved so I figured I’d share what I did to get it up and running!

Login to OSMC via SSH using PuTTy or your client of choice.

Elevate to Super User.
osmc@KODI:~$ sudo su

Update the software repositories.
root@KODI:/home/osmc# apt-get update

Install OpenVPN.
root@KODI:/home/osmc# apt-get install openvpn

Reboot.
root@KODI:/home/osmc# reboot

Create a folder to put your OpenVPN configuration files in.
osmc@KODI:~$ sudo su
root@KODI:/home/osmc# mkdir vpn-conf

Copy your .opvn file/files and your .crt file into /home/osmc/vpn-conf, there are a few ways to copy the files here, I personally like to use PSCP. This
example is using PSCP from a Windows computer.
C:\temp>pscp c:\temp\ca.crt osmc@192.168.1.100:/home/osmc/vpn-conf

Create a new file that will contain your login credentials for OpenVPN
root@KODI:/home/osmc# cd vpn-conf
root@KODI:/home/osmc/vpn-conf# vi login.conf

  • Press Insert
  • Type your Username on first line press enter and type your password on the next
    line.
  • Press Esc, type :wq
Username
Password

Now edit the .opvn file/files of choice to make sure the login.conf and <ca_file_name>.crt file are referenced correctly.
root@KODI:/home/osmc/vpn-conf# vi <filename>.ovpn

  • Find the following lines that begin with:
    • auth-user-pass
    • ca
  • If they exist – edit them accordingly, if they don’t exist you will need to add them.
auth-user-pass /home/osmc/vpn-conf/login.conf
ca /home/osmc/vpn-conf/ca.crt

Let’s test out OpenVPN, the service should start and connect successfully after running this command.
root@KODI:/home/osmc/vpn-conf# openvpn /home/osmc/vpn-conf/<filename>.ovpn

Confirm VPN connectivity by using curl, this should retrieve your VPN’d IP address.
root@KODI:/home/osmc/vpn-conf# curl http://checkip.dyndns.org

If everything checks out and is working so far it’s time to install the OpenVPN Add-On for
Kodi and import a profile. Grab the latest OpenVPN Add-On for Kodi, the quickest way is to just grab it is to use wget right from OSMC, using your web browser right-click on the script.openvpn-x.x.x.zip and Copy the link address.
root@KODI:/home/osmc/vpn-conf# wget -c <paste_link_addr_here>

From Kodi on your TV, go to Settings -> Add-ons -> Install from zip file

  • Select Install from zip file.
  • Navigate to the ZIP file and select it.
  • In the bottom right corner, Kodi notifies when the add-on is installed and enabled.

Now the OpenVPN Add-On for Kodi should be installed… go to Programs > Add-Ons
> OpenVPN from Kodi and import your .opvn files, once complete try to connect. It should work successfully since it’s literally just an interface to the actual OpenVPN service that we just installed and configured.

That’s it! …but if you’d like to take it one step further you can. I personally like to have a certain OpenVPN profile connect at startup of Kodi. It’s pretty simple to do this.

Browse to the userdata folder for Kodi and create an autoexec.py file.
root@KODI:/home/osmc# cd /home/osmc/.kodi/userdata
root@KODI:/home/osmc/.kodi/userdata# vi autoexec.py

  • Type the following where <profile_name> is the profile
    name of the profile you have created in the OpenVPN Add-On for Kodi.
import xbmc
xbmc.executebuiltin('XBMC.RunScript(script.openvpn,<profile_name>)')

Now every time you power on your Kodi box, OpenVPN will launch and the VPN
profile of choice will connect automatically. Cheers and happy streaming!

Code::Blocks in Linux Mint 17.2 and Ubuntu 14.04

codeblocks

Recently I ran into a problem finding a solution for properly installing Code::Blocks on a Linux Mint 17.2 Cinnamon machine. I had the option to opt in and run the application on a Windows lab machine, but I said nah, I want to expose myself more to the linux environment and I want to be able to use my own laptop. So I went ahead and opted to install Code::Blocks on my Linux Mint 17.2 laptop.

After much searching I came across an obscure reference in a forum post to the problem. What was happening is that when I included printf() and scanf() in my simple terminal application it wouldn’t compile or run, the compiler complained about an assumed reference. Code Blocks would also generate errors in regards to stdio.h and that it couldn’t find the file. After further reading the solution is part of the normal compiler/code blocks installation. I was not aware, I’ve never actually compiled code on linux before. Here is what I did to resolve it.

Start by checking that your gcc is up to date. You might not need to but it is always good to run the install as it will update your gcc if it needs to.

sudo apt-get update
sudo apt-get install gcc

The above if up to date, will skip over the installation and tell you that you already have the latest packages installed.

Now go ahead and install Code::Blocks.

sudo apt-get install codeblocks

This will install the application on your computer and you will be able to run it and create projects. However this is where I initially ran into an issue where if I Included stdio.h in the source it would generate an error. Something along the lines of…

… stdio.h: No such file or directory …

There are two things that you need to do to resolve this. You need to install build-essentials and xterm.

sudo apt-get install build-essentials

The above will install the dependencies such as the stdio.h file, however if you go to compile a simple application and run it in command line or bash you will get another error. Generally an XTerm error. You will need to also install XTerm in order for Code::Blocks to be able to open up a terminal window and execute the application.

sudo apt-get install xterm

Once you have all the above packages installed give it a go and you should be able to execute and run simple c/c++ code.