Why I Don't Use Tasker

Tasker is a nifty app for Android. (There’s nothing like it for iPhone/iOS because of sandbox limitations.) It allows all sorts of “when this happens do that”. e.g. When I’m connected to WiFi but it is not my home WiFi, start VPN.

It is complicated to learn, but wonderfully powerful.

I don’t use it. When I was using it, about once or twice a week, my phone would spontaneously reboot. I wouldn’t be using it at the time. It was just sitting in my pocket. Then it would vibrate and I’d pull it out and see that it was restarting.

The only tasks I had at the time were:

  • Chirp when connecting/disconnecting from power.
  • (Disabled) Start VPN when I’m on a foreign VPN.

I don’t have patience for spontaneous reboots right now. To really debug this, one would have to:

  • Install Tasker and let it sit for a couple of weeks with no tasks. If no reboots, continue.
  • Install a task to chirp when connecting to power. If no reboots, continue.
  • Install a task to chirp when disconnecting power. If no reboots, continue.
  • Install other tasks, one at a time, monitoring for 2 weeks for reboots after each one.

Certainly do-able. Not a priority right now.

Practice Revoking a VPN Certificate

Sooner or later, someone is going to lose a laptop or a cell phone and you’ll need to revoke his/her certificate so that the thief can’t use your VPN. When you put a .ovpn file on an client, be certain that client has a good password (e.g. a good screen-lock PIN on your cell phone or a strong Windows password on your Windows PC - with a short timeout on the lock-when-idle.)

On the machine where you built your keys:

  • cd $EASY_RSA
  • Edit openssl*.cnf and change “default_crl_days= 30” to “default_crl_days= 14600” (40 years). If you don’t do this, your CRL will expire in a month and if your CRL expires, the server will refuse ALL logins.

      easy-rsa
      ./revoke-full user-key01-bogus
    

It will respond with “error 23 at 0 depth lookup:certificate revoked”. That’s what you want, but it is phrased confusingly.

If your keys are built on your Pi, execute:

mv ./keys/crl.pem /etc/openvpn/
sudo service openvpn restart

If your keys are built on your Mac:

  • On the Mac, execute:

      scp ./keys/crl.pem pi@raspi:crl.pem
    
  • On the Pi, execute:

      sudo mv ~/crl.pem /etc/openvpn/
      sudo service openvpn restart
    
  • Add the following to /etc/openvpn/server1.conf. (You couldn’t add it until you created a .pem file, or else OpenVPN will throw an error on startup.)

      crl-verify /etc/openvpn/crl.pem
    

And confirm that your client can no longer connect. (Because you revoked access.) Check /var/log/openvpn.log and confirm that you see “CRL CHECK FAILED” in it.

Test again by:

  • Import user-key02-bogus.ovpn into your OpenVPN client
  • Confirm that you can connect with bogus key 2
  • Confirm that you still cannot connect with bogus key 1
  • Revoke bogus key 2
  • Confirm that neither bogus key 1 or 2 can connect.

Note: If your CRL expires, just re-revoke any revoked certificate (or a new one). Revoking any certificate, even an expired one, re-generates the CRL.


Back to Surf Safe at Starbucks

Open Your Firewall on Your Pi VPN

You can’t connect to a VPN on your Pi if your firewall blocks access. Your Pi came with a built-in firewall. We need to open the necessary ports on your Pi.

  • Create a script named /etc/openvpn/firewall-rules.sh. Make it contain this:

      #!/bin/sh
      iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE
      iptables -t nat -A POSTROUTING -s 10.16.0.0/24 -o eth0 -j MASQUERADE
      echo "firewall-rules.sh executed" > /tmp/firewall-rules.sh.log
    
  • You don’t really need that echo statement, but if your VPN doesn’t work, you’ll want to check the timestamp on /tmp/firewall-rules.sh.log to see if the script got executed.

  • Set proper permissions:

      sudo chmod 744 /etc/openvpn/firewall-rules.sh
      sudo chown root /etc/openvpn/firewall-rules.sh
    
  • As root, edit /etc/network/interfaces and put this line BEFORE “iface eth0…”. Do not indent it.

    auto eth0

  • As root, edit /etc/network/interfaces, and append this line after the “iface eth0…” line, indented 4 spaces:

      pre-up /etc/openvpn/firewall-rules.sh
    
  • Allow packet forwarding by editing /etc/sysctl.conf and un-commenting this line:

      #net.ipv4.ip_forward=1
    
  • Commit the packet forwarding changes by running:

      sudo sysctl -p
    
  • Start your server with the command below. I think this also causes it to auto-start at boot. Note that “server1” must match up with the “server1.conf” file in /etc/openvpn:

      sudo systemctl start openvpn@server1.service
    
  • Reboot your Pi.


Return to Surf Safe at Starbucks

Build a UDP VPN Config File from TCP Config

I’d like to have a UDP instance too. As I’ve mentioned, in theory, running a VPN over UDP should work better than running it over TCP. When you have TCP layered over TCP, if you run into network latency, you can have both layers retransmitting, and the upper layer can exacerbate the latency of the lower layer with the extra traffic.

Note: On my Pi, UDP performs MUCH worse than TCP. I haven’t figured out why.

cd /etc/openvpn
sudo cp server1.conf server2.conf

Edit server2.conf and:

  • Change: “daemon openvpn-tcp” to “daemon openvpn-udp”
  • Change: “proto tcp-server” to “proto udp” (NOT udp-server)
  • Change: “port 443” to “port 1194”
  • Change: “server 10.16.0.0 255.255.255.0” to “server 10.8.0.0 255.255.255.0”
  • Change: “log /var/log/openvpn.log” to “log /var/log/openvpn2.log”

While you’re at it, edit server1.conf and change the log from openvpn.log to openvpn1.log.

Run this:

sudo systemctl start openvpn@server1.service
sudo systemctl start openvpn@server2.service
sudo rm /var/log/openvpn.log

Update the firewall/forwarding rules on your telco-router to pass UDP on port 1194 to your Pi.

Locally, make a copy of user-key1.ovpn as user-key1-udp.ovpn.

  • Change: “proto tcp” to “proto udp”
  • Change: “remote your-ip 443” to “remote your-ip 1194”
  • Import it into your OpenVPN client.
  • Connect.
  • Debug.

Back to Surf Safe at Starbucks

Use a Raspberry Pi for a VPN Server

OK, coach. I think I’d like to run my own VPN, but I’m on the economy plan. I can’t afford to buy a new computer.

The Raspberry Pi is nominally $35. That will buy you a multi-core CPU, a gig of RAM, an Ethernet port, etc. What it doesn’t include is

  • Disk
  • Power supply
  • Keyboard
  • Monitor
  • Case

You don’t really need a keyboard or monitor for your VPN server, you’ll use a Micro SD card for the disk, and the Pi uses a micro-USB power supply. You might be able to use your cell phone charger for the power supply, but the Pi needs good power, so splurge $10 and get a really good one.

The latest Pi, an SD Card, a case and a power supply are available in a kit for about $50.


Return to Surf Safe at Starbucks

Grant Only Dad Access to the Home LAN

  • Summary: Per-user config file, Dad on a dedicated IP, firewall to filter except that IP

Maybe you want to access your home LAN while out, but you don’t want your kid’s phone to access your LAN. If he loses that phone and it isn’t passworded, someone could (theoretically) find the phone, pull the certificate off, access your VPN, and then access files on your home LAN.

In this case, you’d like most users’ traffic to be permitted to travel through the router on its way to the internet, but not to travel to your LAN; you want the same for traffic from your laptop, but you also want that traffic to be able to reach your LAN devices. Maybe your kid needs to work on his homework on his PC when you’re at Grandma’s, and you want to remote control his PC from your laptop using VNC.

I’m going to describe how to do this on an ASUS router running OpenVPN with ‘Merlin’ firmware. Merlin has some special capabilities which make this easier. Doing this on a Pi is similar, but some of the interfaces will have different names.

Let’s begin by blocking access to your LAN for all VPN users. Executing this command on your server will block access to the LAN:

  • iptables –insert FORWARD -s 10.0.0.0/8 -d 192.168.0.0/16 -j DROP
    • iptables is the command to add a firewall rule.
    • ”–insert FORWARD” says to add a rule to the packet forwarding table at the beginning of the table.
    • -s and -d specify the source and destination subnets.
    • “-j DROP” says to drop any frames which match this rule.
  • To make this permanent, add the iptables command to a file on the router named /jffs/scripts/firewall-start.
    • You need to use the event ‘firewall-start’ and not ‘openvpn-event’, or else you can wind up with many, many copies of your rule in the table, if the VPN server gets stopped and started between reboots. *You need the first line in the file to be “#!/bin/sh”.
  • “chmod ugo+x” the file and it will get executed when the VPN server starts (or stops).
  • See this for more info on event scripts.
  • Enable user scripts via the router at: Administration » System » Enable JFFS custom scripts and configs

  • Consider also: iptables –insert INPUT -s 10.0.0.0/8 -d 192.168.1.1 -j DROP
    • This blocks VPN users from accessing your router itself. (If you’re using a different net than 192.168.1.x, substitute it.)

When you ran build-key, you ran a command line like:

build-key "user-key-3"

The name you supplied becomes the X509 Common Name (CN) in your key. In this case, the common name will be “user-key03”. Conveniently, when you look in ~/Packages/easy-rsa/keys_xxxxx, you’ll see a file with a name like ‘user-key-3.crt’. The file name of your certificate (less the “.crt”) matches the CN inside the file.

On the router:

mkdir /jffs/configs/openvpn/ccd1/
mkdir /jffs/configs/openvpn/ccd2/
  • Create a file on the router in the ccd1 directory named “user-key-3” (or whatever Dad’s CN is). In this file put something like:

    ifconfig-push 10.8.0.50 255.255.255.0

  • That will assign Dad’s laptop the IP address 10.8.0.50. When a client connects, OpenVPN matches the common name against files in the per-client config directory. If it finds a match, it loads that file as an extension of the OpenVPN file for the current client. Our command pushes the IP address to the client.
  • If no matching file is found, OpenVPN will try to use a default file called “DEFAULT”, so you have a way to specify settings for users who do NOT match a per-client config.
    • Note: We’re going to block access to all users and then grant access to Dad. An alternate approach would be to grant access to all users, and then block most users via a DEFAULT per-client config. I think it is safer to block by default, rather than by ‘DEFAULT’, in case something goes wrong with name matching or per-client config - you want the broken state to deny access, for security.
  • On the router, enable the “Manage Client-Specific Options” option under OpenVPN Server, and press Apply.
    • IMPORTANT: You must do this after you create the config in ccd1. When OpenVPN service is (re)started, Merlin copies from /jffs/configs/openvpn/ccd1 to /etc/openvpn/server1/ccd. jffs files are preserved across reboots. /etc/openvpn is where OpenVPN expects to find files, but it is on a RAM disk, so it vanishes after a reboot.
  • You might read that you can go to your server configuration file (/etc/openvpn/server1.conf) and find the line similar to the line below, and comment it out, to block access:
    • push “route 192.168.1.0 255.255.255.0”
    • (Remember: If your LAN isn’t 192.168.1.x, substitute your LAN’s address in the above.)
  • It won’t work. In the first place, you clients can get to your LAN with or without that route. (I’m assuming that you enabled “Direct clients to redirect Internet traffic”, which sends all client to the rouder.) In the second place, and more importantly, any route you can push (or not push), your users can defeat via the “route” command of their operating system.
  • Important principle: Locking people out is done with your firewall, not routes.

Now edit /jffs/scripts/firewall-start and make it look like this: iptables –insert FORWARD –in-interface tun21 –out-interface br0 -s 10.0.0.0/8 -d 192.168.0.0/16 -j DROP iptables –insert FORWARD –in-interface tun21 –out-interface br0 -s 10.8.0.50 -d 192.168.0.0/16 -j ACCEPT

(You need the lines in that sequence because each one adds a rule to the top of the file, and you need your ACCEPT to override your DROP.)

  • 1st line = If a frame comes in on the VPN, from a 10.x.x.x address, destined for your LAN, drop it.
  • 2nd line = If a frame comes in on the VPN, from Dad’s special address, destined for your LAN, accept it. (This rule will be at the top of the table, so it takes precedence.)

At this point, you should restart your router and confirm that these rules are in place via: “iptables -L FORWARD -v”. Then test it with Dad’s certificate and with someone else’s certificate.

You really ought to ensure that no one else can get Dad’s address. To do that, the end you need to accomplish is:

  • Remove “server 10.8.0.0 255.255.255.0” from your VPN configuration file and replace it with:
    • ifconfig 10.8.0.1 255.255.255.0
    • ipconfig-pool 10.8.0.3 10.8.0.49 255.255.255.0
  • You have to remove the “server” line because it expands (internally) to include an “ifconfig” plus an “ifconfig-pool”

I can think of one way to accomplish this:

It looks like you can assign static IP with an ‘ifconfig-pool-persist’ option, instead of per-client config (if the only per-client config you’re doing is to set static IP). However, I’ve read of people having trouble getting it to work and, as I read things, the server can update this file, which would be a bad idea for your VPN security if it surprises you with an update.


Return to Safe Surfing at Starbucks

Create a Mac OS X Finder Service

Here are some notes on creating a Service for Mac OS X Finder. This will add an item to the Finder Services menu (available under the Finder menu and also by right-clicking on a file in Finder). This particular service will convert a simple .html file into a .rtf.

The basic commands you want to run on the file are:

  • textutil -convert rtf -output “outputfile.rtf” “inputfile.html”
  • touch -r “inputfile.html” “outputfile.rtf”

This will convert the file to RTF (first line) and copy the timestamps from the .html file to the .rtf file (second line).

  1. Launch Automator
  2. File » New » Service
  3. Set: Service receives select files or folders in Finder.app.
  4. Add an action: Run Shell Script. Paste in the following bash statements:

     set -e    # Exit on error
     # This will convert simple (stand-alone) html files to RTF.
        
     html_to_rtf () { 
         d2="$(dirname "$1")" # Do NOT need to escape quote in $()
         f2="$(basename "$1" .html)"
         if [ -d "$d2/$f2.resources" ] ; then return 0 ; fi
         if ! textutil -convert rtf -output "$d2/$f2.rtf" "$1"  ; then return 1 ; fi
         if ! touch -r "$1" "$d2/$f2.rtf" ; then return 1 ; fi
         rm "$1"
     }
        
     for f in "$@" ; do
         g=$(echo "$f" | tr "[:upper:]" "[:lower:]")
         if [[ "$g" = *".html" && -f "$f" && -r "$f" ]] ; then
             html_to_rtf "$f"
         fi
     done
    

Testing an Automator Service is a bother. You want to just press the Run button in Automator, to run it within Automator, but when you run it for real, you will have selected a file in Finder. For testing purposes only, add a step to the beginning of your Automator steps to Get Specified Finder Items, and select some files to test with. After you’ve finished testing, remove it.

File » Save » HTML to RTF

If you need to modify this service at a later date, it will be found in: /Users/username/Library/Services/HTML to RTF.workflow

Convert to PDF - OS X Command Line (Terminal)

To print to PDF (convert) most SINGLE PAGE files in OS X:

cupsfilter foo_name_here > foo.pdf 2>/dev/null

If you run this with a mult-page TIF as input, the output will truncate everything after the first page.

Combine Multiple Images to a Single PDF With Preview on Mac OS X

I wanted to combine multiple TIFF images into a single PDF on Mac OS X. Here’s how:

  • Start Preview.
  • File » Open » open all the files you want, using CMD-click to select.
  • Drag the thumbnails into the desired order
  • File » Print » PDF » Save as PDF