Skip to content

Commit 80bde33

Browse files
committed
local SSL-stripping proxy
0 parents  commit 80bde33

File tree

4 files changed

+150
-0
lines changed

4 files changed

+150
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
node_modules

README.md

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
Simple HTTPS for development
2+
============================
3+
4+
This is a simple SSL-stripping proxy for local development. You don’t need to configure your apache or nginx or vagrant or whatever to use SSL. Just complete a simple setup and all of your local projects will be available over HTTPS without browser warnings.
5+
6+
Requirements & Setup
7+
====================
8+
9+
After getting the code fetch required dependencies:
10+
11+
```
12+
npm install
13+
```
14+
15+
You need to have `openssl` available on your system, since it’s used to generate certs.
16+
17+
Run proxy
18+
=========
19+
20+
For convinience, proxy listens on the default HTTPS port (443) so it needs to be ran as root:
21+
22+
```
23+
$ sudo node index.js
24+
Listening on 443
25+
Generating: /home/bob/.nassau-proxy/ssl.proxy.nassau.pass.key
26+
Generating: /home/bob/.nassau-proxy/ssl.proxy.nassau.key
27+
Generating: /home/bob/.nassau-proxy/ssl.proxy.nassau.csr
28+
Add this cert as a trusted root to get rid of SSL warnings: /home/bob/.nassau-proxy/ssl.proxy.nassau.crt
29+
```
30+
31+
Do as instructed, open the cert in your KeyChain:
32+
```
33+
open ~/.nassau-proxy/ssl.proxy.nassau.crt
34+
```
35+
And set it to "always trust". [Google it if you have any problems](http://superuser.com/questions/404178/importing-a-self-signed-ssl-certificate-on-macos)
36+
37+
Alternate port
38+
==============
39+
40+
If you need to run it on a different port, use `PORT` env:
41+
42+
```
43+
env PORT=8443 node index.js
44+
```
45+
46+
47+
Enjoy
48+
=====
49+
50+
After trusting the generated root certificate (`ssl.proxy.nassau.crt`), your browser will accept any dummy cert generated for your domains by the proxy. Navigate to [https://localhost](https://localhost) to check the results.
51+

index.js

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
var httpProxy = require('http-proxy'),
2+
execSync = require('exec-sync'),
3+
sprintf = require("util").format,
4+
fs = require('fs'),
5+
path = require('path'),
6+
crypto = require('crypto'),
7+
https = require('https'),
8+
sys = require('sys');
9+
10+
11+
var certPath = path.resolve(process.env.HOME, '.nassau-proxy'),
12+
listenPort = process.env.PORT || 443;
13+
14+
function generateCertificate(name, CA) {
15+
var passKeyPath = path.resolve(certPath, name + ".pass.key"),
16+
keyPath = path.resolve(certPath, name + ".key"),
17+
csrPath = path.resolve(certPath, name + ".csr"),
18+
resultPath = path.resolve(certPath, name + ".crt");
19+
20+
fs.existsSync(certPath) || fs.mkdirSync(certPath);
21+
22+
if (false === fs.existsSync(passKeyPath)) try {
23+
console.log("Generating: " + passKeyPath);
24+
execSync(sprintf('openssl genrsa -des3 -passout pass:nassauproxy -out "%s" 2048', passKeyPath));
25+
} catch (E) {}
26+
27+
if (false === fs.existsSync(keyPath)) try {
28+
console.log("Generating: " + keyPath);
29+
execSync(sprintf('openssl rsa -passin pass:nassauproxy -in "%s" -out "%s"', passKeyPath, keyPath));
30+
} catch (E) {}
31+
32+
if (false === fs.existsSync(csrPath)) try {
33+
console.log('Generating: ' + csrPath);
34+
execSync(sprintf("bash -c 'echo -e \"PL\\nmazowieckie\\nWarszawa\\nNassau SC\\n\\n"+name+"\\n\\n\\n\\n\\n\" | openssl req -new -key \"%s\" -out \"%s\"'",
35+
keyPath, csrPath
36+
));
37+
} catch (E) {}
38+
39+
if (false === fs.existsSync(resultPath)) try {
40+
if (CA) {
41+
console.log("Signing the certificate using your own CA: " + resultPath);
42+
execSync(sprintf('openssl x509 -req -days 365 -in "%s" -CA "%s" -CAkey "%s" -CAcreateserial -out "%s"',
43+
csrPath, CA.cert, CA.key, resultPath
44+
));
45+
46+
} else {
47+
console.log("Add this cert as a trusted root to get rid of SSL warnings: " + resultPath);
48+
49+
execSync(sprintf('openssl x509 -req -days 365 -in "%s" -out "%s" -signkey "%s"',
50+
csrPath, resultPath, keyPath
51+
));
52+
53+
}
54+
} catch (E) {}
55+
56+
return {
57+
"cert": resultPath,
58+
"key": keyPath
59+
}
60+
}
61+
62+
// force the CA
63+
var CA = generateCertificate('ssl.proxy.nassau');
64+
65+
var ssl = {
66+
SNICallback: function (domain) {
67+
var domainCert = generateCertificate(domain, CA);
68+
69+
return crypto.createCredentials({
70+
key: fs.readFileSync(domainCert.key),
71+
cert: fs.readFileSync(domainCert.cert),
72+
ca: [fs.readFileSync(CA.cert)]
73+
}).context;
74+
},
75+
key: fs.readFileSync(CA.key, 'utf8'),
76+
cert: fs.readFileSync(CA.cert, 'utf8'),
77+
requestCert: true,
78+
rejectUnauthorized: false
79+
};
80+
81+
var proxy = httpProxy.createProxyServer({ target: { host: "localhost", port: 80 } });
82+
83+
proxy.on('proxyReq', function(proxyReq, req, res, options) {
84+
proxyReq.setHeader('X-Forwarded-Protocol', 'https');
85+
proxyReq.setHeader('X-Forwarded-Proto', 'https');
86+
});
87+
https.createServer(ssl, function(req, res) {
88+
proxy.web(req, res);
89+
}).listen(listenPort);
90+
91+
console.log("Listening on " + listenPort);

package.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"private": true,
3+
"dependencies": {
4+
"http-proxy": "*",
5+
"exec-sync": "*"
6+
}
7+
}

0 commit comments

Comments
 (0)