Route web traffic through a SOCKS tunnel on a private server with a dynamic IP。
Watch US Netflix from the UK using ssh.
When nested procrastination produces something useful
DISCLAIMER: This has been written for educational purposes of learning about net traffic routing. You should probably only employ this if you live in the US.
NOTE: Yes, this, and more, all can be achieved through a private VPN or VPN provider. I prefer the reliance of this solution on essentially only ssh. All parts of the solution are owned by you. There will never be more features to pay for. Your speed is not bottlenecked and always runs at highest priortiy There is no advertising. A SOCKS proxy will be faster than a VPN as it skips an encryption layer. For the implicit problem, I feel the solution given here is optimal.
This basic guide will outline the steps to set up a SOCKS5
proxy over ssh
on
an Amazon Web Services instance in the US to forward net traffic from a machine
with a foreign IP address to the host machine. I set this up for use with
Netflix, but presumably it can be used for other web services that are location
based. If successful, running the command netflix-us
in a terminal should launch
a browser, who thinks s/he lives in the US.
The service is free for a year provided you don't run any other AWS instances on
the account that is used to set up the AWS instance. The AWS 'free tier' provides
you with 750 hours a month (where 31 * 24 = 744
) of time on a linux machine for
12 months, after which it is $0.013
an hour. Or you can just set up another AWS
account, but presumably in a year this method won't work anymore.
The basic steps are outlined below
- Sign up for an AWS account and launch a box in the US (
Ubuntu 16.04
image) - Set up an account with a DDNS
- On the AWS instance:
- Install
docker
- Run a docker image of the
noip
client - Set the configuration for the DDNS client
- Install
- On the host machine:
- Add an
ssh
alias - Add aliases to:
- Set up a background
ssh
tunnel using the instance as a proxy - Run a browser which connects to the web through the proxy
- Kill background
ssh
tunnel
- Set up a background
- Add an
At this point the set up works, and you can check your ip address is from the US by googling 'what's my IP'. You can then add Amazon cloud watch scripts to, for example, only run the AWS instance at specific times of day (to conserve your free hours), where the DDNS and SSH alias will handle the instance's dynamic IP on shutdown and restart.
Account Set Up
AWS
We use AWS to spoof an IP address from a different location. AWS have servers in the US, hence we use their service to set up a virtual machine on their hardware, in the US. This means that any service sending web traffic to them send it to a US address, and so sends them traffic appropriate for the US. We can then read the data from the virtual machine (we 'forward' the traffic to the UK).
- Sign up to AWS here
- Follow the wizard to launch a free EC2 instance in some US region
- AWS is fairly generous with marking out exactly which options are free
- Generate a
.pem
key to set the instance up with and download it- If you're familiar with ssh keys, feel free to continue on to the next section
- Generate an ssh keypair on your host
- A short guide to do this is here, but there are many resources available
ssh
into the AWS instance using the public IP address of the machine, found by clicking the instance in the AWS console and finding 'Public IP' in the details- The
ssh
command syntax isssh -i <pem-key> user@host
- The default amazon user is
ubuntu
- Hence an example command is
ssh -i ~/Downloads/key.pem ubuntu@54.192.170.23
- The
- Place your normal public key in
~/.ssh/authorized_keys
on the instance if you have one, or continue to use the.pem
- Using an authorized key skips manually routing to the
.pem
to login
- Using an authorized key skips manually routing to the
DDNS
A DNS (domain naming service) is how text URLs such as www.google.com
, are
translated to IP addresses, such as 74.125.236.195
, where the IP address is
what the network uses to point to a machine. A DDNS (Dynamic Domain Naming Service)
is useful if our IP address changes often and we don't have to type in an
arbitrary sequence of numbers every time we wish to point to our machine. The
service updates the link between the text URL and IP address.
Why does our IP change? We have the cheapest machine possible on AWS and so our physical location on their servers is the lowest priority. If we shutdown our instance and someone else needs the space, our instance will move to a different IP address, hence we have to go through the hassle of finding the new IP address to re-login to the machine. In general, each time we start our AWS instance, the IP address is not guarenteed to be the same, hence the DDNS gives us a static character string to reference when pointing to our machine.
- Signing up to a DDNS is as easy as signing up to any service. The recommended
service,
noip
, is found here- Sadly, you cannot yet sign in through facebook.
- At some point, you will have to put the password to the service in a plain text file. If, like me, even though you know the file can be fully protected you do not like the idea of seeing your an important password in plain text, choose a different password to ones you usually default to.
On the Remote Instance
Essentially, all we're doing here is setting up a client to ping the remote
instance's IP address up to the DDNS. How does this work? The client lives on
the remote instance, and so can find its own IP address when and if it changes.
We also give the client login details to our noip
account. Every 30 minutes,
we ask the client up to update our noip
account with the IP address of the
machine it lives on. Therefore, when we ask the DDNS who lives at
my-url.ddns.net
, it's up to date to within the periodic polling time.
Docker
Docker is a service that runs other services in 'containers'. The added level of complexity eases set up, as developers can very easily curate the environment that their application will be set up in, minimising errors in simple applications.
ssh
into the remote machine using the public IP address from the AWS console- Install docker using walkthrough here
- If you've not used linux before, these docs are fairly accessible to follow.
The set up amounts to smashing
ctrl-c
,ctrl-v
multiple times to achieve a result that would be otherwise fairly complex.
- If you've not used linux before, these docs are fairly accessible to follow.
The set up amounts to smashing
noip
- Set up the
noip
configuration with the details you signed up to the service with- Change the details in the block below to your own, then copy and paste code into the terminal
# set up config on aws instance - use your own details ofc
mkdir ~/no_ip_config
echo "USERNAME='yupimaki'" | tee ~/no_ip_config/noip.conf
echo "PASSWORD='ILoveDDNS'" | tee -a ~/no_ip_config/noip.conf
echo "DOMAINS='yupimaki.ddns.net'" | tee -a ~/no_ip_config/noip.conf
# Examples: 5 m, 5 h, 5 d. Minimum is 5 minutes.
echo "INTERVAL='30m'" | tee -a ~/no_ip_config/noip.conf
- Run this command to set up the docker image.
docker
commands need to be run asroot
if you didn't run `sudo usermod -aG docker $USER.
docker run \
--name noip \
-v /home/ubuntu/no_ip_config:/config \
-v /etc/localtime:/etc/localtime \
-d --restart=unless-stopped \
coppit/no-ip
- The
noip
client will be downloaded and set running in its own sand-boxed environment.
On the Host (assuming a Ubuntu host)
We add an ssh
alias for ease of using ssh
. Instead of the lengthy command that
was necessary previously, after adding an alias, we can log on to our remote
machine through ssh
simply by typing ssh <alias>
. Aliases are added by
adding new hosts (and configuring them) to the ~/.ssh/config
file. Copy and paste
the below block into the host terminal, with the URL you chose for your remote
machine through the DDNS.
# Add an ssh alias on host
echo "Host US-Jumpbox" >> ~/.ssh/config
echo " Hostname yupimaki.ddns.net" >> ~/.ssh/config
echo " User ubuntu" >> ~/.ssh/config
This will set up an alias such that ssh US-Jumpbox
routes to
ssh ubuntu@yupimaki.ddns.net
, to ssh ubuntu@XX.XXX.XXX.XX
, where the IP
address will have been recently updated by the docker container running on the
remote instance. If you didn't add a public key to the remote machine,
and wish to keep using the .pem
file, add an extra line to ~/.ssh/config
with IdentityFile path/to/key.pem
.
Final Aliases on Host
NOTE: If your host machine isn't running linux, 1) wot r u doin, 2) please refer to the link in the references to crack these last steps on other OSes
Finally, we need an easy way to set up our ssh tunnel to the proxy server and launch a browser which is configured to connect to the web through the proxy.
I find the easiest way (by no means the correct way) to do this is to add some
lines to my ~/.bashrc
file.
# Easy way to kill a process if running on an unknown port
port-kill () {
# Find offending process's port
{
# Truthy hack to handle error if no process with that name is found
ps -C $1 -o pid= &> /dev/null && port=$(ps -C $1 -o pid=)
} || {
echo "No process found with name $1"
return
}
# Get process name by port ID
process_name=$(ps -p ${port} -o comm=)
# Option to kill found process
read -r -p "Are you sure you want to kill ${process_name}? [y/N] " response
response=${response,,} # tolower
if [[ $response =~ ^(yes|y)$ ]]
then
kill ${port}
fi
}
## Run and kill commands
# Must not have a google-chrome session open.
# Seems to be a bug in chrome that you can't force start with a new session
alias netflix-us="ssh -D 1089 -f -C -q -N US-Jumpbox && google-chrome --proxy-server='socks5://localhost:1089'"
alias kill-ssh="port-kill ssh"
Breaking down the final aliases, netflix-us
is composed of two statements.
ssh -D 1089 -f -C -q -N US-Jumpbox
We already know what ssh US-Jumpbox
does. Explaining the other flags;
-D 1089
sets up [D]ynamic port forwarding on the local port1089
throughssh
-f
[f]orks the process and runs it in the background-C
[C]ompresses the data before sending it through thessh
pipe-q
sends allSTDOUT
andSTDERR
messages to/dev/null
, i.e. it is [q]uiet
google-chrome --proxy-server='socks5://localhost:1089'"
This command simply starts google chrome, however specifies that it connects to
the web through a proxy server. The server is our localhost
at port 1089
,
which we know is dynamically routing our web traffic through the US.
Now all you have to do to watch US Netflix (whilst respecting copyright,
[provided you live in the US]) is to run the command us-netflix
in the terminal.
Unfortunately there seems to be a small bug in google-chrome
, where you cannot
force the browser to run in a new session, so for the routing to work, chrome
cannot already be open. To get around this, use one browser reading traffic
through the proxy, and other for general surfing.
When done, tear down the tunnel using kill-ssh
, or simply leave it running.
Thanks for reading,
Akhil
References
- Route traffic using SOCKS tunnel
- Shout out to Richard who showed me how to use a DDNS。
from https://github.com/yupimaki/netflix-and-socks
No comments:
Post a Comment