Oct 032013
 
 October 3, 2013  Posted by at 4:15 pm documentation, vpn Tagged with: , , ,  No Responses »

This outlines a typical VPN implementation with server, clients and routing. Using Attitude Adjustment 12.09

Set a password in LuCI web interface to enable ssh access. Then ssh to device and do the following.


opkg update
opkg install openvpn-openssl openvpn-easy-rsa

It is recommended to create the certificate authority on another computer, even one that is not connected to any network! Although, that requires more work than I usually care to do.

Because I have done an upgrade accidentally and overwritten my easy-rsa directory, and thus all keys/certs along with it, I now move this directory into /etc/config/openvpn-config.

mkdir /etc/config/openvpn-config
mv /etc/easy-rsa/ /etc/config/openvpn-config/
cd /etc
ln -s config/openvpn-config/easy-rsa

(this creates a relative symlink)

== CERTIFICATE AUTHORITY FOR OPENVPN ==
edit the following or don’t if you want to enter it manually on certificate creation.
At the end of the /etc/easy-rsa/vars file:

# These are the default values for fields
# which will be placed in the certificate.
# Don't leave any of these fields blank.
export KEY_COUNTRY="US" <-*edit*
export KEY_PROVINCE="CA" <-*edit*
export KEY_CITY="SanFrancisco" <-*edit*
export KEY_ORG="Fort-Funston" <-*edit*
export KEY_EMAIL="me@myhost.mydomain"
export KEY_EMAIL=mail@host.domain
export KEY_CN=changeme <-*edit - servers hostname*
export KEY_NAME=changeme
export KEY_OU=changeme
export PKCS11_MODULE_PATH=changeme
export PKCS11_PIN=1234


clean-all
(run this to ensure your starting with a clean slate)
build-ca
build-dh
build-key-server servername_server
(don’t set a challenge password, Answer yes to sign the certificate and yes to commit.)

Instead of using UCI syntax (that I struck out below) we can break this out to be more openvpn standard and troubleshooting friendly. Also, I have added the ability to set static ip’s for the openvpn clients.

== OPENVPN SERVER CONFIG ==
Overwrite /etc/config/openvpn with the following config

config openvpn server_openvpn
option enabled 1
option config /etc/config/openvpn-config/server.conf

config openvpn lan
option enable 1
option port 1194
option proto udp
option dev tun
option ca /etc/easy-rsa/keys/ca.crt
option cert /etc/easy-rsa/keys/servername_server.crt
option key /etc/easy-rsa/keys/servername_server.key
option dh /etc/easy-rsa/keys/dh1024.pem
option ifconfig_pool_persist /tmp/ipp.txt
option keepalive "10 120"
option comp_lzo yes
option persist_key 1
option persist_tun 1
option status /var/log/openvpn-status.log
#option log /tmp/openvpn.log
option verb 3
option server "10.128.241.0 255.255.255.0"
option topology subnet
option client_to_client 1
list push "dhcp-option DOMAIN lan"
list push "dhcp-option DNS 192.168.233.1"
list push "route 192.168.233.0 255.255.255.0"

The following is the openvpn server config (that is called by /etc/config/openvpn) in /etc/config/openvpn-config/server.conf

float
port 1194
proto udp
dev tun
comp-lzo yes
ifconfig-pool-persist /tmp/ipp.txt
status /var/log/openvpn-status.log
mute 5
log /tmp/openvpn.log
keepalive 10 120
persist-key
persist-tun

dh   /etc/config/openvpn-config/easy-rsa/keys/dh2048.pem
ca   /etc/config/openvpn-config/easy-rsa/keys/ca.crt
key  /etc/config/openvpn-config/easy-rsa/keys/server.key
cert /etc/config/openvpn-config/easy-rsa/keys/server.crt

mode server
tls-server
topology subnet
push "topology subnet"
ifconfig 10.128.241.0 255.255.255.0
route-gateway 10.128.241.1
push "route-gateway 10.128.241.1"
ifconfig-pool 10.128.241.20 10.128.241.254 255.255.255.0
push "route 192.168.233.0 255.255.255.0"
push "dhcp-option DNS 192.168.233.1"
client-to-client

#client-config-dir /etc/config/openvpn-config/clients

If you want to enable the static client ip assignments be sure to uncomment the client-config-dir above and make a directory as such.
mkdir /etc/config/openvpn-config/clients
write a file inside the clients directory with the same name as the common name of the openvpn client certificate.
For example, in a file /etc/config/openvpn-config/clients/jason
ifconfig-push 10.168.84.2 255.255.255.0

/etc/init.d/openvpn enable
/etc/init.d/openvpn restart

cd /etc/config/openvpn-config/
openvpn --config server.config

check for errors
cat /tmp/openvpn.log

Check for errors in the openvpn config syntax using uci show
uci show openvpn
The following will be displayed if there are no syntax issues. Use of the quotes are common mistakes.
openvpn.lan=openvpn
openvpn.lan.enable=1
openvpn.lan.port=1194
openvpn.lan.proto=udp
openvpn.lan.dev=tun
openvpn.lan.ca=/etc/easy-rsa/keys/ca.crt
openvpn.lan.cert=/etc/easy-rsa/keys/servername_server.crt
openvpn.lan.key=/etc/easy-rsa/keys/servername_server.key
openvpn.lan.dh=/etc/easy-rsa/keys/dh1024.pem
openvpn.lan.ifconfig_pool_persist=/tmp/ipp.txt
openvpn.lan.keepalive=10 120
openvpn.lan.comp_lzo=1
openvpn.lan.persist_key=1
openvpn.lan.persist_tun=1
openvpn.lan.status=/var/log/openvpn-status.log
openvpn.lan.verb=3
openvpn.lan.server=10.128.241.0 255.255.255.0
openvpn.lan.topology=subnet
openvpn.lan.client_to_client=1
openvpn.lan.push=dhcp-option DOMAIN lan dhcp-option DNS 192.168.233.1 route 192.168.233.0 255.255.255.0

== NETWORK ==

Now lets setup the tun interface so that we can add zones
networ-interface-vpn0
in /etc/config/network or in LuCI.

config interface 'vpn0'
	option proto 'none'
	option ifname 'tun0'

 

 

== FIREWALL ZONE ==

Create a zone called openvpn_zone with vpn0 network.
openvpn_zone

in /etc/config/firewall

config zone
	option input 'ACCEPT'
	option output 'ACCEPT'
	option name 'openvpn_zone'
	option network 'vpn0'
	option forward 'REJECT'

 

We now explicitly declare the forwards like this.
openvpn_zone to lan zone allow

config forwarding
	option dest 'lan'
	option src 'openvpn_zone'

openvpn_zone to wan allow, if you want openvpn clients to use the wan for example if using redirect-gateway

config forwarding
	option dest 'wan'
	option src 'openvpn_zone'

openvpn_zone to lan allow

config forwarding
	option dest 'openvpn_zone'
	option src 'lan'

 

== FIREWALL TRAFFIC RULE ==

Allow the openvpn server to accept connections from clients out in the world.
openvpn2device

config rule
	option target 'ACCEPT'
	option src 'wan'
	option proto 'udp'
	option dest_port '1194'
	option name 'openvpn2device'
	option enabled '0'

An overview of traffic rules

openvpn_traffic_rules

 

 

 

 

 

 
** NOTE: Occasionally, I have had to reboot for the above zone’s to work **

== Optional firewall rules to use, instead of using the zones. Not recommended ==
in /etc/firewall.user

# This file is interpreted as shell script.
# Put your custom iptables rules here, they will
# be executed with each firewall (re-)start.

# Allow all traffic in and out of the tun interface.
iptables -A input_rule      -i tun+ -j ACCEPT
iptables -A output_rule     -o tun+ -j ACCEPT
# This rule will allow traffic towards internet from tun
iptables -A forwarding_rule -i tun+ -j ACCEPT
iptables -A forwarding_rule -o tun+ -j ACCEPT

 

== USER CONFIGURATION ==
build-key jason
or you can run build-key-pass to issue a key that asks the user to enter the password before it is used (more secure).
Once you have completed the build-key, being sure to answer yes to signing the certificate and commit.

Now you need to get the keys for jimmy and the ca.crt (not ca.key!). Each client needs these files to connect.
scp /etc/easy-rsa/keys/jason.* jason@192.168.1.78:jason-vpn
scp /etc/easy-rsa/keys/ca.crt jason@192.168.1.78:jason-vpn

Then create the client config in the same directory as the crt’s and keys. If your installing this on a windows box then you should run unix2dos on all the files.
Create a file called jason.ovpn in jason-vpn directory as such

nobind
comp-lzo
dev tun
remote hostname-to-server 1194 udp
client
tls-exit
ca ca.crt
cert jason.crt
key jason.key
remote-cert-tls server
mute 5
resolv-retry infinite
explicit-exit-notify
keepalive 10 60
ping-timer-rem
persist-tun
persist-key
#redirect-gateway def1

I have a script to help with client config http://jasonschaefer.com/stuff/easyrsa-user-setup-openwrt.sh.txt

Test the server by connecting from off-site.
cd into your local config directory where your certs, keys and .ovpn config are.
sudo openvpn jason.ovpn
enter your sudo password

You should see something like this at the end of the openvpn output:

Fri Feb 28 22:19:01 2014 /sbin/ifconfig tun0 10.128.241.4 netmask 255.255.255.0 mtu 1500 broadcast 10.128.241.255
Fri Feb 28 22:19:01 2014 /sbin/route add -net 192.168.233.0 netmask 255.255.255.0 gw 10.128.241.1
Fri Feb 28 22:19:01 2014 Initialization Sequence Completed

and you will see a tun interface

# ip a
38: tun0: mtu 1500 qdisc pfifo_fast state UNKNOWN qlen 100
link/none
inet 10.128.241.4/24 brd 10.128.241.255 scope global tun0
valid_lft forever preferred_lft forever

and the correct route has been pushed to you

# ip r
192.168.233.0/24 via 10.128.241.1 dev tun0

== REVOKING A USERS KEY ==

add the following line to /etc/config/openvpn:
option crl_verify /etc/easy-rsa/keys/crl.pem

run “revoke-full” with users key as argument:

revoke-full [key-to-revoke]

restart openvpn:

/etc/init.d/openvpn restart

Jul 112012
 
 July 11, 2012  Posted by at 4:48 pm documentation, scripts Tagged with: , , , ,  No Responses »

I have a Dreamhost VPS account and have been running out of memory and experiencing the dreaded forced reboots dh impose. I found it difficult to identify the offending sites that take up all that memory on my server. Every time I login and run top it was too late or I would find a website being crawled by a search bot. How to find a trend over time, without getting too complicated? My solution was to track the memory usage with ps and write that to individual files, then sort all those files and derive the top offenders in one list. Which is web accessible (or not) for easy viewing later. If my VPS reboots, I can go back to the individual files before the forced reboot and get details of whats causing the problem.

#!/bin/bash

#no trailing slash. Be sure this dir exists.
path=/home/jason/jasonschaefer.com/memusages

logfile=index.txt

#how many days to keep files, remove after..
removeafter=5

# ps -[e]everything, [o]format
# rss is resident set size in kilobytes
# user:20 username with 20 char space so it won't revert to uid on usernames longer than 8 chars
# cmd:40 running command with 40 char column, stime=start time of cmd
# [h]hide headers, --sort=rss sorts on rss column
/bin/ps -eo rss,user:20,cmd:40,stime,pid h --sort=rss > $path/mem`date +"%F_%k-%M"`.txt

# sort unique, numeric on column 5 the pid, so we don't show duplicate processes.
# then sort numeric, reverse on column 1 the memory usage, write the top 200 lines to our logfile.
/usr/bin/sort -u -n -k 5 $path/mem*.txt | /usr/bin/sort -n -r -k 1 | head -n 200 > $path/$logfile

#find files older than $removeafter days and remove them
/usr/bin/find $path -mtime $removeafter -exec rm -fr {} \;

Don’t forget to make it executable
chmod 755 /home/jason/memusages.sh

Then setup to run in cron, to run every ten minutes of every hour, every day, every month and every day of week. Change as needed.. I have it running every minute right now. Depending on your setup you may need to run this as root to see all system processes.
crontab -e
*/10 * * * * /home/jason/memusages.sh