Use nginx as Non-Transparent SSL Proxy ====================================== Introduction ------------ 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 - may refer to [Bind9 Server How-To](https://help.ubuntu.com/community/BIND9ServerHowto) on Ubuntu Community 2. install nginx with [HttpSslModule](http://wiki.nginx.org/HttpSslModule) and [HttpSubModule](http://wiki.nginx.org/HttpSubModule) - download lastest version on [nginx website](http://nginx.org/en/download.html) - 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` ----------------------- ```nginx server { listen 443; server_name api.example.org; # 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 proxy_pass https://api.example.org; # 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; } } ```