Nginx as forward proxy for HTTPS

64,282

Solution 1

Seems like nginx does not support forward proxy mode with SSL. You will need to use something like Squid instead. Here is a link with more explanation from nginx's author: HTTPS and nginx as Forward Proxy.

Solution 2

Just to clarify: as I wrote on my blog's comment feed, nginx doesn't handle CONNECT method calls which are used to establish a raw TCP connection to a remote host through an HTTP proxy - which makes sense, considering that nginx is not supposed to work as a forward proxy, it just happens to work quite well for regular HTTP regardless.

Nginx just literally has no idea what to do with those method calls, that's why the error messages in the logs are rather useless. I've always found myself using privoxy for HTTPS: http://www.privoxy.org/ - it's insanely easy to set up, too. But it's still impossible to filter or mangle the content of HTTPS relays, because HTTPS connections are handled with a raw connection through the CONNECT method and the server has no idea what it's relaying.

Solution 3

If you don't mind compiling nginx from source, you could install ngx_http_proxy_connect_module. The following worked for me in Debian 9 "Stretch" on a Raspberry Pi (after I added deb-src URLs to /etc/apt/sources.list and did apt-get update):

cd /tmp &&
apt-get source nginx &&
git clone https://github.com/chobits/ngx_http_proxy_connect_module &&
cd nginx-* &&
patch -p1 < ../ngx_http_proxy_connect_module/proxy_connect.patch &&
sudo apt-get install libpcre3-dev &&
./configure --add-module=/tmp/ngx_http_proxy_connect_module &&
make && sudo make install

Then edit /usr/local/nginx/conf/nginx.conf and make it look like this (I've included an example of domains you want to block, which works with both SSL and non-SSL proxying):

user www-data;
worker_processes auto;
events { }
http {
    server_names_hash_bucket_size 128;
    server {
        listen       8888;
        server_name  spam.example.com *.spam.example.com;
        server_name  spam2.example.com *.spam2.example.com;
        access_log off;
        return 404;
    }
    server {
        listen       8888;
        server_name ~.+;
        proxy_connect;
        proxy_max_temp_file_size 0;
        resolver 8.8.8.8;
        location / {
           proxy_pass http://$http_host;
           proxy_set_header Host $http_host;
        }
    }
}

Then run /usr/local/nginx/sbin/nginx. It will quite happily coexist with Debian's stock nginx package if you're also running a production webserver on port 80 and don't want to risk messing with that (but make sure to start the /usr/local version separately on boot); alternatively, with more configuration you could run both services from the nginx you've compiled. But if you do set your compiled nginx to run on a port that your firewall allows traffic to, beware you'd have to check manually for nginx security updates as the Debian package system will no longer do it for you.

Solution 4

I just followed the instructions from Silas S. Brown and I was able to compile a Nginx binary which can deal with forwarding and SSL. I bundled everything together into a Docker image. The Dockerfile and the configuration is here on GitHub: https://github.com/reiz/nginx_proxy.

The Nginx Docker image in this Docker Hub repository can handle SSL connection and forwarding: https://hub.docker.com/r/reiz/nginx_proxy/.

Share:
64,282
Admin
Author by

Admin

Updated on September 18, 2022

Comments

  • Admin
    Admin over 1 year

    While I was able to successfully configure nginx to proxy HTTP traffic (using this guide), all attempts to proxy HTTPS requests resulted in code 400 (Bad Request).

    Nginx debug logs weren't helpful at all:

    2013/06/05 14:38:33 [info] 74946#0: *589
        client sent invalid request while reading client request line, client: 127.0.0.1,
        server: google.com, request: "CONNECT google.com:443 HTTP/1.1"
    

    What are these CONNECT requests? Is it even possible to proxy_pass HTTPS requests in nginx?

    Update

    Need to add that a proxy server is part of my web development workflow/toolkit. It's a great way to test/debug client-side JavaScript in production environment (using rewrites before the proxy).

    Also nginx's config language is arguably a programming language in it's own right. It has variables!

  • Admin
    Admin almost 11 years
    Thanks! The thread you linked is 4 years old, but it also seems to me it's still impossible.
  • Zorayr
    Zorayr almost 11 years
    If you need a proxy for debugging, try mitmproxy.
  • Robert Reiz
    Robert Reiz over 6 years
    I had to tweak some of the commands but overall your answer worked for me. Many Thanks!
  • code rider
    code rider about 4 years
    This was mighty helpful and saved me quite some time.