Skip to content

Use text messages to start and stop your personal VPN

License

Notifications You must be signed in to change notification settings

mcrowson/vpn_on_demand

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

22 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

VPN on Demand

Send text messages to start and stop your own VPN on AWS for super cheap.

Having a personal VPN gives you more control over logs and easily toggling the VPN instance can keep costs way down. This approach does it by combining the following tools:

  • AWS t2.nano instance running OpenVPN
  • A Twilio phone number to receive the text messages
  • An API via AWS Lambda and API Gateway to receive requests from Twilio and start/stop the EC2 instance

Costs

Here are the services used in this VPN setup and a discussion of their costs

EC2 t2.nano

Normally the cost of running your own VPN is paying for the instance to be up all the time. If you are still within the first 12 months of your AWS account, you can leave this t2.nano up for the entire year and it will be within the free tier. However if you are trying to conserve your free tier hours or are beyond the first twelve months, running the t2.nano is 0.00058/hr.

EC2 Elastic IP

$0.0005/hr when the node is offline.

AWS API Gateway

Similar to EC2, API Gateway is free for the first 12 months up to 1 million calls per month. After 12 months it costs $3.50 per million API calls.

AWS Lambda

The first million Lambda calls are always free each month.

Twilio

We stay within their free tier usage in this guide which allows for purchasing a single phone number that can call/message pre-approved numbers.

Set Up Your VPN

Clone the repo:

git clone https://github.com/mcrowson/vpn_on_demand
cd vpn_on_demand

This guide uses Python 3.6, Zappa and jq. jq just makes things a little easier when pulling data out of the AWS CLI JSON responses.

The VPN Instance

The instance here is a t2.nano running OpenVPN. Let's launch an EC2 instance using the AWS CLI

The instance should only have port 1194 open for the VPN, but we'll need to shell into it for the setup. So the security group will have both ports 22 and 1194 open initially. We will close port 22 after setup is complete.

SECURITY_GROUP=$(aws ec2 create-security-group --description "OpenVPN Port" --group-name VPN --output text)
aws ec2 authorize-security-group-ingress --protocol udp --port 1194 --cidr 0.0.0.0/0 --group-id $SECURITY_GROUP
aws ec2 authorize-security-group-ingress --protocol tcp --port 22 --cidr 0.0.0.0/0 --group-id $SECURITY_GROUP

Next create a key pair to login to the instance with. If you already have a named key pair that you want to use, skip this step. This command lets AWS create a key pair, and saves your private key to ~/.ssh/vpn_key.pem. We will use this key to shell into the EC2 instance.

aws ec2 create-key-pair --key-name VPN --output json | jq -r ".KeyMaterial" > ~/.ssh/vpn_key.pem
chmod 400 ~/.ssh/vpn_key.pem

Launch an EC2 instance with the security group and the key pair we made above. The image-id given here is the latest Ubuntu 16.04 LTS at the time of writing. Once we launch the instance we also want to get the public IP so we can shell in and setup OpenVPN. Note the public IP because we will need it when setting up the VPN. We will also want to give the instance an elastic IP so it doesn't get a new public IPv4 with each stop/start.

INSTANCE_ID=$(aws ec2 run-instances --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=VPN_Instance}]' --image-id ami-759bc50a --instance-type t2.nano --key-name VPN --associate-public-ip-address --output json --security-group-ids $SECURITY_GROUP | jq -r ".Instances[] | .InstanceId")
aws ec2 wait instance-running --instance-ids $INSTANCE_ID
ELASTIC_ID=$(aws ec2 allocate-address --domain vpc --output json | jq -r ".AllocationId")
aws ec2 associate-address --instance-id $INSTANCE_ID --allocation-id $ELASTIC_ID
PUBLIC_IP=$(aws ec2 describe-instances --instance-ids $INSTANCE_ID --query 'Reservations[*].Instances[*].PublicIpAddress' --output text)
echo $PUBLIC_IP

Once the instance finishes launching, shell into the box so we can setup OpenVPN.

ssh -i ~/.ssh/vpn_key.pem ubuntu@$PUBLIC_IP

Now that you're in the instance, add docker. This makes setting up OpenVPN much easier.

curl -fsSL get.docker.com -o get-docker.sh
sh get-docker.sh
sudo usermod -aG docker ubuntu

At this point you need to logout and log back in to pickup the group permissions. Once you're back in the instance. The OpenVPN comes from https://github.com/kylemanna/docker-openvpn. For our purposes we mostly follow the quick start steps on the README there and make two changes:

  • Replace VPN.SERVERNAME.COM with your public ip that we've echoed above. You will also give this in the Common Name prompt when following the instructions in the README.
  • Add --restart always to the OpenVPN container so it restarts when we restart the instance. It would look like:

docker run -v $OVPN_DATA:/etc/openvpn -d -p 1194:1194/udp --restart always --cap-add=NET_ADMIN --name ovpn kylemanna/openvpn

After finishing the quick start guide there, you should have some CLIENTNAME.ovpn file on the instance.

Log out of the instance and copy your new key to your local machine.

scp -i ~/.ssh/vpn_key.pem ubuntu@$PUBLIC_IP:CLIENTNAME.ovpn CLIENTNAME.ovpn

Now open up your favorite OpenVPN client and try to connect with your new key. If everything has worked correctly you should be able to Google "what's my ip" and it shows you the public ip of your instance.

With a working key locally, we can turn off port 22 now. No more shelling needs.

aws ec2 revoke-security-group-ingress --group-id $SECURITY_GROUP --protocol tcp --port 22 --cidr 0.0.0.0/0

Now load up your favorite mobile OpenVPN client for iOS or Android and put your key on your phone (different approaches here based on mobile platform).

Create Your Free Twilio Account

Setup a phone number that can receive your text messages and fire off the events for starting and stopping your VPN. Twilio has a free tier that allows you to have a single phone number. This phone number can only be used to call/message approved phone numbers.

  • Head over to Twilio and signup/login.
  • Create a Project
  • From the Twilio Console grab the ACCOUNT SID and AUTH TOKEN values. We will need those later.
  • Navigate to the Purchase a Number page and buy a new number with SMS capabilities.

Deploy the API

The API will be running on a combination of AWS Lambda and API Gateway powered via Zappa.

There are a few pieces of information we need to customize here for your implementation. Open up the zappa_settings.json file:

  • Set the environment variables.
{
    "TWILIO_ACCOUNT_SID": "your_value",  # The ACCOUNT SID value from the Twilio console
    "TWILIO_AUTH_TOKEN": "your_value",  # The AUTH TOKEN value from the Twilio console
    "TWILIO_PHONE_NUMBER": "+14565557890",  # The Twilio phone number you purchased
    "ALLOWED_SENDER": "+14565557890",  # Your cell phone number that was verified on Twilio
    "EC2_INSTANCE_ID": "i-1234567890",  # The instance id of your VPN
    "EC2_REGION": "us-east-1"  # The region of your EC2 instance
}
  • Replace EC2_INSTANCE_ID in the extra_permissions setting with your actual instance id to give lambda permission to turn it on/off
  • Replace the value in s3_bucket with the name of a bucket for holding your project during deployment. You can set this to some random value and Zappa will create the bucket for you.

Once that is done, create a virtual environment and deploy the API.

python3.6 -m venv env
source env/bin/activate
pip install -r requirements.txt
zappa deploy

When the deployment process finishes, Zappa spits out your new API Gateway URL.

Tell Twilio to Send Messages to Your API

The API is live now. So we are going back to Twilio to tell it to send incoming messages to the API.

  • Go to the Twilio Phone Numbers page and select your number.
  • Towards the bottom of the page, add your API Gateway endpoint to the incoming message as a webhook.

When your new number receives a text, it will send a POST request to the API we have deployed.

That's it! Try sending some texts to the Twilio phone number with "VPN on" and "VPN off" to make sure it works.

If you remember to turn off the VPN when you're done using it, costs should be pennies.

About

Use text messages to start and stop your personal VPN

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages