Ansible use ssh tunnel for http proxy


If you need to use a web proxy on an ansible node to get to the Internet, you can use the ansible role I hacked together. I had a need for using an ad-hoc ssh tunnel to a proxy server.

So your node will need an ssh key for automatic authentication to the proxy server over ssh. The role just executes a “ssh -N -p 22 -L 1234/localhost/1234” and sets up the environment hash which includes http_proxy and https_proxy.

Check out the role at my github page.

Code walkthrough

My roles always have incredibly basic main.ymls because I always use a subdirectory architecture.
- hosts: all
- include: tasks/main.yml
- handlers/main.yml
- vars/main.yml

Now the tasks/main.yml file is where half of the work occurs.
# File: /etc/ansible/roles/use-proxy/tasks/main.yml
- name: clear any ssh tunnel
shell: ps -ef | grep -iE -- "ss[h].*{{local_proxy_port}}" | awk '{print $2}' | xargs kill -9
ignore_errors: yes
- name: start ssh tunnel
shell: nohup ssh -N -p {{proxy_server_ssh_port}} {{proxy_server}} -L {{local_proxy_port}}/localhost/{{proxy_port}} &
notify: stop ssh tunnel

It’s pretty clear what each task is doing. The start ssh tunnel opens up an ssh connection. If it is successful, it notifies the stop ssh tunnel handler which will execute at the end of the play.

- name: stop ssh tunnel
shell: ps -ef | grep -iE -- "ss[h].*{{local_proxy_port}}" | awk '{print $2}' | xargs kill -9

The handler searches for and kills the ssh connection that is using the specified port.

The vars/main.yml file is important because you must customize it to your environment.
proxy_port: 3128
local_proxy_port: "{{proxy_port}}"
proxy_server_ssh_port: 22
http_proxy: "http://localhost:{{local_proxy_port}}"
https_proxy: "http://localhost:{{local_proxy_port}}"

How you use this role in a playbook is at the beginning of the list of roles. You also need to define the environment as seen below.
- name: Playbook that uses an ssh tunnel for http_proxy
hosts: test
remote_user: root
environment: "{{ proxy_env | default(omit) }}"
- { role: use-proxy, when: usehttpproxy is defined and usehttpproxy|bool == true }
- example

You can run this playbook with the use-proxy role and environment as is against any hosts that need the http proxy. To minimize traffic back and forth, just comment out the use-proxy role, and run the play against the regular hosts.