Skip to content

Instantly share code, notes, and snippets.

  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
What would you like to do?
Guide to set up nginx as non-transparent SSL proxy, which subsitutes strings in the server responses

Use nginx as Non-Transparent SSL Proxy


Many mobile apps have back-end API servers. They usually rely on the API replies to determine whether certain information is supposed to be shown. If the API responses could be manipulated on the fly, we may easily fool an unmodified app to expose some private data.

This manual guides you to set up nginx as non-transparent SSL proxy, which just subsitutes strings in the server responses (i.e. man-in-the-middle attack ourself). For both server-side (their API servers) and client-side (your device), the whole process is almost transparent.

Step by Step

  1. create fake DNS records
  2. install nginx with HttpSslModule and HttpSubModule
    • download lastest version on nginx website
    • configure with --with-http_ssl_module --with-http_sub_module parameters
  3. generate SSL certificate
    • openssl genrsa -des3 -passout pass:x -out example-org.pass.key 2048
    • openssl rsa -passin pass:x -in example-org.pass.key -out example-org.key
    • openssl req -new -key example-org.key -out example-org.csr
    • openssl x509 -req -days 365 -in example-org.csr -signkey example-org.key -out example-org.crt
  4. configure nginx.conf
    • see attached example below
  5. set up your client device
    • install SSL cert (i.e. example-org.crt here)
    • set major DNS server (to your fake one)
  6. fire up nginx and enjoy!

Example of nginx.conf

server {
    listen 443;

    # SSL support
    ssl on;
    ssl_certificate /path/to/example-org.crt;
    ssl_certificate_key /path/to/example-org.key;

    location / {
        # proxy to the original site
        # prevents gzip compression, which cannot be processed by HttpSubModule
        proxy_set_header Accept-Encoding ''; 
        # substitute specific string in the original response
        sub_filter '"accessible":false' '"accessible":true';
        # do substitution more than once
        sub_filter_once off;
        # set up filter types (text/html by default)
        sub_filter_types application/json; 
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment