Here is a working python script I have to do exactly what you are wanting, but it only works on PIA VPN. There are some other particulars, like you have to use a PIA server that supports it. The US ones don't at this time.
I have a Pi2, Raspbian 8 "Jessie" and the latest transmission from the repository. Works great....
I have it set to run every hour with a cron job, so if my port changes it will update the port accordingly.
Code: Select all
#!/usr/bin/env python
import urllib
import urllib2
import json
import sys
import netifaces
import os
# put your VPN username and password below
YOUR_USERNAME = "XXXXXXXX"
YOUR_PASSWORD = "XXXXXXXX"
# This should be a long random string, or something that no one else is going
# to be able to guess. Don't share this amongst multiple computers on the
# same VPN account. If you have more than one computer, use a different client
# ID for each. I recommende the output of the Linux "uuidgen" command, but
# you can really just use whatever.
YOUR_CLIENT_ID = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
# The interface your VPN uses. We use this to look up your local IP, as
# required by the port forwarding API. Probably you won't have to change this
# unless you really know what you're doing (e.g., if you have more than one
# VPN tunnel on the same system or something)
VPN_IFACE = "tun0"
# This is the API URL. Don't change this.
API_URL = "https://www.privateinternetaccess.com/vpninfo/port_forward_assignment"
# Look up the local IP from the VPN interface
try:
local_ip = netifaces.ifaddresses(VPN_IFACE)[netifaces.AF_INET][0]["addr"]
except ValueError,e:
print "No such interface. Are you connected?"
sys.exit(-1)
# Make the API request to the webserver
request = urllib2.Request(API_URL, urllib.urlencode(
{
"user":YOUR_USERNAME,
"pass":YOUR_PASSWORD,
"client_id":YOUR_CLIENT_ID,
"local_ip":local_ip
}
))
# Gather the (possibly multi-line) JSON response and create a python dict
# out of it
response = ""
for line in urllib2.urlopen(request).readlines():
response += line
resp = json.loads(response)
# Now either print out the forwarded port or an error message.
if "port" in resp:
print resp["port"]
port = resp["port"]
cmdstring = 'transmission-remote -n "userXXXXX:passXXXXX" -p %d' % port
os.system(cmdstring)
elif "error" in resp:
print "Error: %s" % resp["error"]
sys.exit(-1)
else:
print "Error: no idea what failed!"
sys.exit(-2)
Of course, you have to add your own passwords and usernames where needed. Look for XXXXX's in the above. And I can't promise on some systems you won't have to tweek it. This is a copy of a script on the PIA forums, in it's original form it just printed out the port, I added the bits about auto-updating transmission with the info. This is the bits I added.
Code: Select all
port = resp["port"]
cmdstring = 'transmission-remote -n "userXXXXX:passXXXXX" -p %d' % port
os.system(cmdstring)
and this at the top:
Here is the cron I created to run it:
Code: Select all
0 * * * * /usr/bin/python ~/vpnport.py >> /home/pi/log/vpnport.log 2>&1
You want that little logging piece on the end, every hour it spits out the "success" message from transmission, and the port the script spits out, so you know what it is trying to change it to. If you just use system log, only the transmission bit makes it to the syslog. The print pieces of the script are lost, and you want those if there are issues.
I didn't write this script, so I don't know a whole lot about it aside from the bits I added. It worked "out of the box" for me, so I never had to mess with the original.