Ansible – Allowing outbound HTTP access from firewalled/DMZed hosts via SSH Reverse Proxy and Apache HTTPD mod_proxy

Production Servers often live in heavily-firewall-restricted DMZ networks, making it hard to update them with YUM, etc. because they often do not allow outbound HTTP access.

If you are using ansible to update RPMs on a RHEL or CentOS server, it can be handy to temporarily allow access for those servers to the YUM repositories on the internet, say for example, if you need to update the tzdata RPM to work around the issue with LEAPSECOND.

Assumptions:

  1. You have ansible set up and working
  2. You run ansible stuff as ‘ansibleuser’ with a home directory of ‘/home/ansibleuser’
  3.  You have hosts that are managed by ansible that do not have outbound HTTP access on their own
  4. You have Apache HTTPD installed on the ansible server (in my case a CentOS 6 x86_64 server)
  5. You will run an HTTP proxy that listens on and is accessible only from the ansible server 127.0.0.1 port 9050

Setup:

First, the HTTPD proxy:

  1. Install the Apache HTTPD server and SSL support on the ansible server using “yum install httpd mod_ssl”
  2. Add a file called /etc/httpd/conf.d/http-proxy.conf
  3. Put the following in that file:

    #———————————————————–
    # -v- Enable HTTP Forward Proxy
    #———————————————————–
    # Purpose: This will set up an HTTP Forward Proxy that
    # listens on port 127.0.0.1:9050
    #———————————————————–
    Listen 9050

    <VirtualHost 127.0.0.1:9050>
    ProxyRequests On
    SSLProxyEngine On

    #Deny from All, but allow localhost (127.0.0.1)
    <Location />
    Order Deny,Allow
    Deny from all
    Allow from 127.0.0.1
    </Location>
    </VirtualHost>
    #———————————————————–
    # -^- Enable HTTP Forward Proxy
    #———————————————————–

  4. Restart the httpd service to pick up the changes (or reload it, if preferable)

Second, the ansibleuser /home/ansibleuser/.ssh/config

  1. Use a bash command to put .ssh/config entries into your ansibleuser’s .ssh/config file so ansible can use them

    for x in $( cat /etc/ansible/hosts | grep -v “^#” | grep -v “\[” ) ; do echo -e “Host ${x}\nRemoteForward 127.0.0.1:9050 127.0.0.1:9050\n” ; done | tee /home/ansibleuser/.ssh/config

  2. Edit your ansible playbooks, adding the following snippet to any task that needs http_proxy
    Note: this works with curl and yum, unsure about other utilities

        environment:
    http_proxy: http://127.0.0.1:9050

  3. That will set the environment up so that curl and yum automatically use that proxy when connecting

Now, when you run your ansible playbook, the following will happen:

  1. The ~/.ssh/config file will have an entry in it for each of your hosts
  2. This entry will cause ssh to forward the remote port 9050 back to port 9050 on the ansible server
  3. The ansible server has an apache httpd http proxy listening on that port 9050, so it is ready to proxy connections to the yum repositories or general http sites in the case of curl.
  4. When the ansible task starts, the environment snippet will cause the yum or curl or other utility to see this environment variable when it executes.
  5. CURL and YUM will use the http_proxy environment variable and send all their traffic to port 9050 on the ansible host being used.
  6. This will, thanks to the SSH connection from step 2 above, send the traffic to the ansible server, which will proxy it out to the interent, allowing your DMZed nodes to get their updates, etc.

Thanks for reading!

Leave a comment