Vagrant and Ansible

Showing some basic concepts of Ansible using a VM provisioned with Vagrant. For details see the Ansible and Vagrant documentation.

Objectives

As little demo project I want to create an Ansible role ‘torproxy’ which installs and runs tor, listening for proxy clients on an IP which is accessible on the LAN.

A bit of background (caution: very simplistic): Tor is a network of nodes, which is used to disguise the origin of requests. You can use tor as proxy in the webbrowser. If you then access a website, the request is passed through several nodes in a practically untraceable way. Only the last node (the ‘exit node’) will access the website, requests the information and passes it back to you through the tor network again. You can also use tor to provide a service within the tor network itself. This service is run completely anonymously without revealing any information about the physical host itself. I. e. you can basically set up tor for four different purposes:

  • As internal node only to support the network anonymously.
  • As exit node to support the network. But your IP address will be visible to the outside, and recognizable as part of the tor network. Caution: This can lead to problems.
  • Running an own service within the tor network.
  • Providing a proxy to the tor network, e.g. to use with your browser.

I want to do the latter, set up a machine which provides a proxy to the tor network usable within the LAN.

Note: Alternatively you can use torbrowser which bundles a ‘security hardened’ Firefox with a tor proxy running in the back. Although more secure, I don’t really like it. I prefer to use my own browser with a separate tor proxy.

Stuff you need

Set up a VM with Vagrant

First create a directory for our project called ‘torproxy’.

Then create a Vagrant config which spins up a Debian/Stretch virtual machine using VirtualBox, with 1GB RAM and 1 CPU. Assign IP 192.168.99.99 to it. Copy over the local public SSH ID so that we (and Ansible) can simply login via vagrant@192.168.99.99. If you don’t have one, create it now with ssh-keygen!

torproxy/Vagrantfile

Vagrant.configure("2") do |config|
  config.vm.box = "debian/stretch64"
  
  config.vm.network "private_network", ip: "192.168.99.99"

  config.vm.provider "virtualbox" do |vb|
    vb.name = "torproxy_vm"
    vb.memory = 1024
    vb.cpus = 1
  end

  config.vm.provision "shell" do |s|
    ssh_pub_key = File.readlines("#{Dir.home}/.ssh/id_rsa.pub").first.strip
    s.inline = <<-SHELL
      echo #{ssh_pub_key} >> /home/vagrant/.ssh/authorized_keys
    SHELL
  end
end

Create Ansible role ‘torproxy’

We could put everything in a playbook, but it’s cleaner and reusable if we create an Ansible role for our task.

Create the directory structure roles/torproxy/tasks. Then put everything we need to install tor into main.yml:

torproxy/roles/torproxy/tasks/main.yml

---
- name: Install some required packages, apt-transport-https
  become: true
  apt:
    name: apt-transport-https
    update_cache: yes

- name: Install some required packages, policykit-1
  become: true
  apt:
    name: policykit-1

- name: Add tor apt key
  become: true
  apt_key:
    id: A3C4F0F979CAA22CDBA8F512EE8CBC9E886DDD89
    url: https://deb.torproject.org/torproject.org/A3C4F0F979CAA22CDBA8F512EE8CBC9E886DDD89.asc

- name: Add tor apt repository
  become: true
  apt_repository:
    repo: deb https://deb.torproject.org/torproject.org stretch main

- name: Install tor
  become: true
  apt:
    name: tor
    update_cache: yes

- name: Enable SOCKS proxy
  become: true
  lineinfile:
    path: /etc/tor/torrc
    regexp: '^#SocksPort 192'
    insertafter: '^#SocksPort 192'
    line: SocksPort :

- name: Allow only local network access
  become: true
  lineinfile:
     path: /etc/tor/torrc
     regexp: '^#SocksPolicy rej'
     insertafter: '^#SocksPolicy rej'
     line: SocksPolicy accept /24
  notify:
    - restart tor

The last line in the task’s main.yml triggers a ‘restart tor’ handler. We still have to create that one. Create the roles/torproxy/handlers directory and add the following to the main.yml:

torproxy/roles/torproxy/handlers/main.yml

---
- name: restart tor
  become: true
  service:
    name: tor
    state: restarted

Create Ansible playbook

torproxy/playbook.yml

---
- hosts: torproxy_vm
  roles:
    - role: torproxy
      vars:
        proxy_port: 8888

Add the VM to the Ansible hosts

/etc/ansible/host

[torproxy_vm]
192.168.99.99

[all:vars]
ansible_user=vagrant

Run it

In the torproxy project directory

vagrant up # Spin up the VM
ansible-playbook playbook.yml # Run the tor proxy installation

Then set the proxy settings of your browser to Socks5 proxy 192.168.99.99 port 8888 and enjoy the anonymity.