Browse Source

Merge branch 'tls'

Alan Shreve 12 years ago
parent
commit
abc4684e45

+ 9 - 2
Makefile

@@ -17,14 +17,21 @@ client: deps
 	go install -tags '$(BUILDTAGS)' main/ngrok
 
 release-client: BUILDTAGS=release
-release-client: bindata client
+release-client: bindata-client client
 
 release-server: BUILDTAGS=release
 release-server: server
 
 release-all: release-client release-server
 
-bindata:
+certs:
+	go get github.com/inconshreveable/go-bindata
+	./bin/go-bindata -i assets/tls/snakeoil.crt -o src/ngrok/server/tls/snakeoil.crt.go -m -p tls -f snakeoilCrt
+	./bin/go-bindata -i assets/tls/snakeoil.key -o src/ngrok/server/tls/snakeoil.key.go -m -p tls -f snakeoilKey
+	./bin/go-bindata -i assets/tls/snakeoilca.crt -o src/ngrok/client/tls/snakeoilca.crt.go -m -p tls -f snakeoilCaCrt
+	./bin/go-bindata -i assets/tls/ngrokroot.crt -o src/ngrok/client/tls/ngrokroot.crt.go -m -p tls -f ngrokRootCrt
+
+bindata-client:
 	go get github.com/inconshreveable/go-bindata
 	./bin/go-bindata -b release -i assets/page.html -o src/ngrok/client/views/web/static/page.html.go -m -p static -f PageHtml
 	./bin/go-bindata -b release -i assets/highlight.min.css -o src/ngrok/client/views/web/static/highlight.css.go -m -p static -f HighlightCss

+ 0 - 6
assets/ngrok.js

@@ -160,12 +160,6 @@ ngrok.controller({
                 $scope.$apply(function() {
                     $scope.txns.unshift(JSON.parse(message.data));
                 });
-
-                /*
-                $("pre code").each(function(i, e) {
-                    hljs.highlightBlock(e)
-                });
-                */
             };
             
             ws.onerror = function(err) {

+ 25 - 0
assets/tls/ngrokroot.crt

@@ -0,0 +1,25 @@
+-----BEGIN CERTIFICATE-----
+MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEU
+MBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFs
+IFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290
+MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEwNDgzOFowbzELMAkGA1UEBhMCU0Ux
+FDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRUcnVzdCBFeHRlcm5h
+bCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0EgUm9v
+dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvt
+H7xsD821+iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9
+uMq/NzgtHj6RQa1wVsfwTz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzX
+mk6vBbOmcZSccbNQYArHE504B4YCqOmoaSYYkKtMsE8jqzpPhNjfzp/haW+710LX
+a0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy2xSoRcRdKn23tNbE7qzN
+E0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv77+ldU9U0
+WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYD
+VR0PBAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0
+Jvf6xCZU7wO94CTLVBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRU
+cnVzdCBBQjEmMCQGA1UECxMdQWRkVHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsx
+IjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENBIFJvb3SCAQEwDQYJKoZIhvcN
+AQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZlj7DYd7usQWxH
+YINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5
+6wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvC
+Nr4TDea9Y355e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEX
+c4g/VhsxOBi0cQ+azcgOno4uG+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5a
+mnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ=
+-----END CERTIFICATE-----

+ 29 - 0
assets/tls/snakeoil.crt

@@ -0,0 +1,29 @@
+-----BEGIN CERTIFICATE-----
+MIIFDDCCAvQCAQEwDQYJKoZIhvcNAQEFBQAwTDELMAkGA1UEBhMCVVMxEzARBgNV
+BAgTCkNhbGlmb3JuaWExEjAQBgNVBAoTCW5ncm9rLmNvbTEUMBIGA1UEAxQLKi5u
+Z3Jvay5jb20wHhcNMTMwNjAzMDQyMzAwWhcNMjMwNjAxMDQyMzAwWjBMMQswCQYD
+VQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTESMBAGA1UEChMJbmdyb2suY29t
+MRQwEgYDVQQDFAsqLm5ncm9rLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCC
+AgoCggIBANouXC6wJacPIFYEiKIGGhliShxsy181LJ064ZTD3ARMTi9ONOsRkHXT
+oM0CV1ZNDniPp3JILiGL52FPp0hdJegQ+pzz/gDjX0h9MCWexM4sqLpY0TfEqk9l
+HWKPJg+ODK8wa1/wuQOK++m/XY3wcbZgLj23EHcGybl/xGJkaeaqGNvrJo/4RgSL
+/jTpp0dDWKUmKBpTH4PuD6bkl8qKQAP1eul6ZS+Gr/llFYJWqwgd3SD3Wh/61Y4n
+6sDusem2NQltnlFwe5VS1LfopVtO3e2N5fveEUdbg2YDs7evNYVK+1i0kjo0dD3D
+tbmhe13OQ/baufxcHc1xjtGsJ57ws8nePL4eo+vFuD5Qjc9ESfzunSem0hC5AJgF
+rsWzIYsr7UsiuKG4gQdD17L+DogVCqRcdYXugrPEJONi8YG3eRRP/Q9klX4PWy7O
+Zj7KX/xBrvS5GeDNqrDVsPL0W24FJ//Sus7BSF0fc5DSYqtD4Zgf1GRi0+xSa3m9
+AgJwWOHm6iC0mHwddozPLd+CP/M7PYzPRDiWY/ehoCFiqRAglYO0mhKyJvoTOjq6
+TBYYp/8LcbqfqUkI6DSnZ2fNdXKDyirMSOT4K1ug1MHaq8obucLqx+5Hie5d6CKR
+gnN15sJwGKIy27fg6LAzi1GWuCzZ1kHqjuQh3oVfuBKnFfsdLUnFAgMBAAEwDQYJ
+KoZIhvcNAQEFBQADggIBADael2+SR8LC5xNCBcu4eqmil30Whb7qqr16EHU/MSQb
+nmFMxBqTa2B8RDZIIkb7LukH8rsAdU8Bzkc2yRdjoAfEMMcJA/fMpwuaXI5cuaKV
+idZFpNUyR+K5UG/CntcCvwzZp4//g+LVK9qPDZ2BJmA/PMR6OphRwRwG+ruSLUCi
+ywgFFhNlPMpPZ49vsFm/Q0A4JmLpZXaARt53zNbNiHT1FgTP/9L1HIpkbfoFQT6R
+pB/VYe8O+GmrwaL3l+L8aO07JRM+u0OKNPxOgxWgE7UngiWulXpnIHAXYxTVMQ8V
+1IYutv9bYJ/+TAy9Kxzc4Q33K+5qvS58GCAjOF10NnHkiTQPbhUWISoj21eZJ1hb
+Z4BbC5z/Y8zNbMao0ACF0QmlnXlt0YrkjkcZQuqerzpC6YMw32vsemREc55X9UQM
+mVbnDah4xyPM+yNIg/uKHVTYJ6+4TttWEp1JGRaP2EOYr0yGe4XFFrKIPH2DlApM
+nNfqR+Mfx9WZS3n6FuWPGWUDBye2fdxOjW9Jwc/+JDR3BsS65LlzPrs6C8TcNnnD
+EdWJ4klYzWkuSdUiV1EXbsB1sSIKmUud2f4vJuOqlBsgS8/mTxjk123uXaN9zaN6
+A9cMWQI2MbobK0HErkk0QyNTtVTKumEEko/c2ktsn8lrdJcKqCeQ9EKwp6r0Lmtp
+-----END CERTIFICATE-----

+ 51 - 0
assets/tls/snakeoil.key

@@ -0,0 +1,51 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIJKAIBAAKCAgEA2i5cLrAlpw8gVgSIogYaGWJKHGzLXzUsnTrhlMPcBExOL040
+6xGQddOgzQJXVk0OeI+nckguIYvnYU+nSF0l6BD6nPP+AONfSH0wJZ7EziyouljR
+N8SqT2UdYo8mD44MrzBrX/C5A4r76b9djfBxtmAuPbcQdwbJuX/EYmRp5qoY2+sm
+j/hGBIv+NOmnR0NYpSYoGlMfg+4PpuSXyopAA/V66XplL4av+WUVglarCB3dIPda
+H/rVjifqwO6x6bY1CW2eUXB7lVLUt+ilW07d7Y3l+94RR1uDZgOzt681hUr7WLSS
+OjR0PcO1uaF7Xc5D9tq5/FwdzXGO0awnnvCzyd48vh6j68W4PlCNz0RJ/O6dJ6bS
+ELkAmAWuxbMhiyvtSyK4obiBB0PXsv4OiBUKpFx1he6Cs8Qk42Lxgbd5FE/9D2SV
+fg9bLs5mPspf/EGu9LkZ4M2qsNWw8vRbbgUn/9K6zsFIXR9zkNJiq0PhmB/UZGLT
+7FJreb0CAnBY4ebqILSYfB12jM8t34I/8zs9jM9EOJZj96GgIWKpECCVg7SaErIm
++hM6OrpMFhin/wtxup+pSQjoNKdnZ811coPKKsxI5PgrW6DUwdqryhu5wurH7keJ
+7l3oIpGCc3XmwnAYojLbt+DosDOLUZa4LNnWQeqO5CHehV+4EqcV+x0tScUCAwEA
+AQKCAgBb6Ru8L0gtUBn3IoHMf3WPK/C8eLhTqzrYIW3WFYwh42MsWm3AeO26NSSQ
+OGRCXsOx1hJb+jw0tZMLU1rNCTBmyoBIjiB6j04cY2Bc+L0/fWC236ODMr3sJFR0
+qIkIFHcTdfpFuEq4S1xD4/GtUZUVlv7j0LKG8b0Y/9HjARn7qbw/KJheHeChGbhE
+4gkt5Bj7uU87h7jHAwpk6/dlw0ekY00b/guSMdL/5K1i8s+p46q7sHeu8SP1dqtW
+Cze3lKJTDnKbLB9jkDk8IC1IgbjL0fMIX0w4Gz0HRJf40T5ioGuxup+/FUnCmyd6
+w6QMqE/JNesTfFqxqRzZBwTJ1+xkXkSFmFhZ9McfxmEtozau0LH6TtkGmHvfmn6/
+I8ImlIRyHGOUVHsEAR8c7aD9dag0LbXmjyolfin8Dow130/G3hTXYnDETx66k1RT
+Bh6kDEYvuxvFqkXYKRAu5u11vQA9udYqN4i+htQ2OOYOEKNX8Kxy562rXgd85MyT
+eTL4Dmh/6J7VtWG4nN2G8pnj5Lg99Q8fzEFQmFLFcK0kJwHu04pJaqrHL+uHHd5T
+KOfPAr0pUbeu2sVd9chgDhADUE1/8YPhSCsHudM4No4tDCZVEqKJ1pGLCpUw3H1v
+h0aA/B582p2CGFpGoInKfFKvUbYt2neDZZQygmYCUHywqNxQAQKCAQEA/H0MCJYV
+VRRLufZkz3fpC+wT+coqbguwrT2bpVBuNdvyDKYIkbcSDtIVNsO/1p1/CGormDll
+k1jNFhR+lqBB8QQfb1ZetPohxzPNncPiJypb9Uivu7GG1MNUHJUecFt8uITcY93s
+UgRBVsCpLgUP7SF6m1Mpu2BaXQ/sEM8dYCSmt4Fax7LW00cIpLleZmCXoc/jsTUM
+ixYTM5r5UWXBhl196Lfu+WjTmoxGgFeTwF8x1wuo7mQvPfripvUX/bjGR4o5JQOw
+1I0XK13yrhFkEAIV61nHBGiyhmJShPaSI2uDudx0ZkfuUIM1UFvqeqWsjATaLmOW
+X7lE0qNg75lsRQKCAQEA3Tcqgviss9a4Owr0BagleObUnTMFzk8bgpemNdzi47eG
+7C572Wx8Gs6XgNbO28lpE0PD7KU/Rvt36wP9mzGiP0M3Zr4h81AfLvftoMMs6ytk
+wHJOdtPUCZqvnblvKOI409nGnoUD+3nfH/qqHk4ZL3fn4vHbxwModZfOXRrH2hJr
+EVqAnnexi9S0JbJJxdcSlBMI5vQMKGLCj52C2mfcF+XRMuF88bwfJ7Xcb3yhyv8i
+pXHHZZ9QKE7eG76UO+EGKz8gn3wWKuh5HXp3HoyKidgzXtPIbu8fd4UzXl/BTMFc
+jWAG0Ycsm5dTobQ0Yo0Xeju5Hs5QCtItY7OAFsH/gQKCAQBBCTC9UXNjO9wZpYbo
+DdoAkSnAELwHJom2xgS+e044H1Rkv6u7ZO2I1cJTHe7fKChdkYNzLW2lm50QD+1f
+fR4fJ9G1CwlQEpH6zrQq7Bbnwbh4IOXrMdoqGbojtqFljZs9qDNgofxKUABIiU3K
+pdEpYpNDSROZyULdb8l9tuu5JRewcuhgQgel2kk2rOzM8Bp+up7KuYBmnyQJCeUo
+e05y/sf81sv+gGrpBzLtwiEzzxF2c/FqnnGwxFv3Z3BrkVm5ebgoeZ/l0AXkzMlC
+3wXoPbFJsxFZaGJ7zP22dBDGgN4oVMnCwsp3AKUN8u8d8mjUlDdi9ZH5TC6XFzBT
+5zAFAoIBAFCjlXmc0MfV096iBYYyX0aNTp/nQ4yLRcn7IfmshYDhG+vonfkKFMto
+1819gHaaGxWMtFUFf+WOMY6YK9Bw7WYGSKHJWXLqmBN1CUh7HVq0vMtyX6vtV/QQ
+UUg7movau0BuuHp8npEDQhTUOUNG0ON+4CbYZ3dKbWtAZVeHNacG48S1qwEZPL1u
+UiUTstTNq9YSgkI+YFgweCAGGPcouRB1FCdqDzPHkcvV/X8efZQUITsSGM+wnXW0
+Gj8e38ZcJvWI04mPoD0P9WaLh/S44p+REljU9tGJlXzqL2mNmlcyfVyDzrh+gAJP
+zYq6uAXczNwf/UF/j6oCJ82aV2z0VwECggEBAJga2Kb1ovNLMQ8Vum1tE8BOku9D
+hTVpz+sFugZuY5Dzl9sPGT3UXGjZZ8pGEGpLPQK2YP5yc+ehCng3ePtXV0sPUR5W
+17jibM2JYFkR9RJCCA8c++2OwxZTVJcSDUkHG7cpl5QLbzOJAWG78EziiNqZEyC0
+RsYKPad6e0enYtPvYlnCYr77Y4KN6mU5Ot3OzqGeP4++dUMznL21vb2wmO6xHLR0
+Mwa6w7fIXYNAOuCk0GMeYzSHZT7ZYytUUhiiTVbHZuazJR6JyR7yf3dnjkPfRVHe
+qLsKIVNbyWayop61fNZWfN4FgLMmUDzCNNDz9sFX09Jm1QaEo+Dun7Dw8Ss=
+-----END RSA PRIVATE KEY-----

+ 30 - 0
assets/tls/snakeoilca.crt

@@ -0,0 +1,30 @@
+-----BEGIN CERTIFICATE-----
+MIIFFDCCAvwCCQCkbN0RG/o15DANBgkqhkiG9w0BAQUFADBMMQswCQYDVQQGEwJV
+UzETMBEGA1UECBMKQ2FsaWZvcm5pYTESMBAGA1UEChMJbmdyb2suY29tMRQwEgYD
+VQQDFAsqLm5ncm9rLmNvbTAeFw0xMzA2MDMwMzUxNTZaFw0yMzA2MDEwMzUxNTZa
+MEwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRIwEAYDVQQKEwlu
+Z3Jvay5jb20xFDASBgNVBAMUCyoubmdyb2suY29tMIICIjANBgkqhkiG9w0BAQEF
+AAOCAg8AMIICCgKCAgEA6QryXeKl8AWWa9uG2UbSOpooH74zLkXs3FZfk9gKvqki
+zXXQCRmtU6Dyn0+OuS3sE/rRmZAsSjkQG/YDtdE/SgL4dV6S62qiQngPokjR0USh
+PC4Hwb8TjM9W5Cd+owVzMQ0vl0AYhQk8Yc/0vX+zDOwmRWGjNKPq422usF9CJFc/
+8QY+ODJDHun8VVAkq3XfcPXgytHIqxvSJnYgDouFCA+GTsKp/65S5cigSlIrQZbH
+775cTWhCjvYnq6gzyrk3RiGdb1IGuIJftMJxuJyJVbfTFtqgMGTmjHZxiLvM7dz7
+j/bmrz4PvnhbQSZZLhsvP1o8mxnoNMpo/To5tHp/Ts6b5FQNL7FHpmOVLAoQ3FdX
+VryTjoSjiE3JLDGZINQ9MFEPgPzR8mrzqFo/6e7uB4AYlKoQo01Kzx+YmVwRKEtr
+VCTRZRcl66+gMkcX0ryoVnggjIWWu4d8uAh3jf++Kd0Djb/l7DCPpEgSJwZYTjCL
+Z6SxiBwQ4o9dEQadMGgk3tlDFCBsrHoq7NyzvXHP0BF2HKb8KREBEKCIuQj9RChW
+g07zmOpjngWs0CXaYly+TDP+5DZCMGD9kmXkQY9q/zqqvMt+T+/TBK9lwUsoi2Uc
+v93wS+TNu06aRopqPo9YZr38ka3xKPiO964pk2BoFN57g767G8k9TbhkBxitvFUC
+AwEAATANBgkqhkiG9w0BAQUFAAOCAgEARf/hVYntzUwFUgQrWD0l/UaCBgrlvxVC
+yUa8Isj3vezAhFSyZntEL+ELFv8vvQbtBGHH/tCn76WuqjwOjVL23yxkaJsrnR9+
+TRNFnVeB8157+IF6HKzLCL/HIAiQ0kw/2OSLD0lZnAkg24A0/9SHcpI5GA0WlThE
+4GqgcUiN9m+mL8jWG3gj+SXC7IcVS3vAvS1J7Kz0NzTh1dYkQNWJlauO2Qn95T99
+plkPPh87yZO9a9bxpX9PUJkTJzOwUkZISRZEbTA0CfspUpq/phzuTViy7o2fr+To
+xVVa2aKT912vlQadWw5oqEK7xyxTqsYwV7CUljtCnhpS7wOZhwzI3qUk9HKH0Rt9
+/HQsANuSikZosNvdM3/hv3c5DRUOwKiKdbgZCyqQf8XSeJRM1iQvcHo8U8kEJEEt
+dmftn+0gH3RPsV028+7XD6wraqfc7dzNzLnq2rDLSAfG3T7pp0n19JyUieWsTR45
+pGcwNpXDk+weqQKknwbNoha3o51Xq/1nhRtqrUPIEgOnBWBCV8vkhXMh9Vbe+oAm
+LmweN1Mr6MjrHWddVn+JGcB5p+AMWr8zE+bhpPCAnupFR98z3fbOleMCWq6Q+hMP
+MUThqJROHamHRIJ3Iz8whIrj7EKkDBKLEfE1ExS3B9VQ+YdHy6sjexdmCIQgElq4
+4SMuY/JkZlo=
+-----END CERTIFICATE-----

+ 1 - 1
src/ngrok/client/cli.go

@@ -94,7 +94,7 @@ func parseProtocol(proto string) string {
 func parseArgs() *Options {
 	server := flag.String(
 		"server",
-		"ngrok.com:2280",
+		"ngrok.com:4443",
 		"The remote ngrok server")
 
 	httpAuth := flag.String(

+ 5 - 4
src/ngrok/client/main.go

@@ -6,6 +6,7 @@ import (
 	"io/ioutil"
 	"math"
 	"net/http"
+	"ngrok/client/tls"
 	"ngrok/client/ui"
 	"ngrok/client/views/term"
 	"ngrok/client/views/web"
@@ -32,7 +33,7 @@ const (
  */
 func proxy(proxyAddr string, s *State, ctl *ui.Controller) {
 	start := time.Now()
-	remoteConn, err := conn.Dial(proxyAddr, "pxy")
+	remoteConn, err := conn.Dial(proxyAddr, "pxy", tls.Config)
 	if err != nil {
 		// XXX: What is the proper response here?
 		// display something to the user?
@@ -53,7 +54,7 @@ func proxy(proxyAddr string, s *State, ctl *ui.Controller) {
 		return
 	}
 
-	localConn, err := conn.Dial(s.opts.localaddr, "prv")
+	localConn, err := conn.Dial(s.opts.localaddr, "prv", nil)
 	if err != nil {
 		remoteConn.Warn("Failed to open private leg %s: %v", s.opts.localaddr, err)
 		return
@@ -180,7 +181,7 @@ func control(s *State, ctl *ui.Controller) {
 	}()
 
 	// establish control channel
-	conn, err := conn.Dial(s.opts.server, "ctl")
+	conn, err := conn.Dial(s.opts.server, "ctl", tls.Config)
 	if err != nil {
 		panic(err)
 	}
@@ -295,7 +296,7 @@ func Main() {
 				case ui.CmdRequest:
 					go func() {
 						var localConn conn.Conn
-						localConn, err := conn.Dial(s.opts.localaddr, "prv")
+						localConn, err := conn.Dial(s.opts.localaddr, "prv", nil)
 						if err != nil {
 							log.Warn("Failed to open private leg %s: %v", s.opts.localaddr, err)
 							return

+ 102 - 0
src/ngrok/client/tls/addtrust.key.go

@@ -0,0 +1,102 @@
+package tls
+
+import (
+	"bytes"
+	"compress/gzip"
+	"io"
+	"reflect"
+	"unsafe"
+)
+
+var _addTrustCrt = "" +
+	"\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\x74\x94\x5b\xcf\xaa\x38" +
+	"\x14\x86\xef\xf9\x15\x73\x6f\x26\xa2\x82\xca\xc5\x5c\xb4\xa5\x40" +
+	"\xd1\x02\xe5\x28\xdc\x71\x12\x04\xf1\x88\x16\xf9\xf5\xe3\xe7\xb7" +
+	"\x33\xd9\x33\x7b\x76\x93\x26\xcd\xdb\x64\xad\xb7\x5d\xcf\x5a\x7f" +
+	"\x7e\x2d\x88\x75\x62\xfd\x81\xb0\xeb\x13\x8d\x20\xe0\xe3\x8f\x2a" +
+	"\x50\x42\xb0\xd5\x20\x04\x86\x65\x05\x38\x81\xa0\x7a\x6f\x1f\x58" +
+	"\xb0\x6a\xaf\x75\x7b\xd0\x15\x2e\x42\xc0\x02\x0d\xa8\xf0\x49\xd9" +
+	"\x9d\x23\x16\xab\x21\x63\x3a\xe6\xa6\xef\xfa\x38\x10\x28\x24\x3a" +
+	"\x98\x05\x18\xd5\x74\xcb\x22\xb7\x0d\x0d\x73\x96\x2f\x58\xc5\x02" +
+	"\x32\x98\x0d\x68\x61\x65\x85\x10\xdc\x7d\x23\xd0\xda\x44\x73\x5f" +
+	"\xc5\xce\x12\x09\x0e\xa5\x42\x0f\x5f\x59\xa7\xdd\x05\xa2\xb9\x41" +
+	"\x80\xa0\x9d\xec\xdc\x45\xb6\x30\x6f\xd4\x23\x9c\x80\x4f\x16\x15" +
+	"\x0f\x47\x98\xe8\x6e\x90\x9f\xc2\xb1\x40\x50\x2b\x0d\xf7\x98\x77" +
+	"\x72\x9d\x21\xa8\x32\x0f\x7a\xd9\x5c\x11\xdf\x0e\xa4\x9d\xea\x03" +
+	"\x4e\xd5\x60\xa4\x2a\xe6\x96\x5a\x8d\xb6\x76\x7e\x6b\xe4\xbf\x1a" +
+	"\xcf\x46\xbc\xa5\xa0\xfd\x38\x86\x35\x45\x81\x18\x0c\x82\xa6\x02" +
+	"\xef\xdb\xe6\xd9\x47\xe2\xcf\x36\x35\x44\xbd\x98\x9b\xdf\x6e\xb6" +
+	"\x78\x98\xfd\xaf\x1b\xe1\x6d\x27\x08\x35\x50\xf9\x5d\x28\x16\x73" +
+	"\xe5\x95\x8e\xf8\x40\x11\xf8\x64\x01\x03\x4d\x7e\xfe\x17\x77\x57" +
+	"\x8b\xc9\xce\x7c\xc4\x11\xaf\x98\x88\xab\xa0\x53\x9e\x42\xa1\xbe" +
+	"\x2b\xf0\x7e\xb7\xca\x62\x73\x73\x4e\x48\xfd\xcc\x2d\xc0\x30\x84" +
+	"\x0c\xa8\x55\x85\x1d\xf0\x75\xcf\xce\xe8\x7d\x86\x60\xbb\x5f\xe8" +
+	"\x8d\xd3\xad\x2b\x80\xb7\xfe\xa9\xf2\x8f\xcf\x5e\x30\x56\xc3\x5d" +
+	"\x5d\xcf\x67\x93\x83\x3d\x1f\xfb\x65\x86\x7d\x7b\x77\x41\x47\xba" +
+	"\x4f\xec\xfd\x33\xb8\xae\xdb\x89\xa8\xea\x0f\xdb\x19\x27\x61\x1f" +
+	"\x68\xb7\xe8\xf8\xea\x82\xe8\x8c\xb8\xb7\xbb\x65\xdb\xcb\x4e\x11" +
+	"\x1e\xf4\x3a\xb5\xc6\xaa\x37\x9a\xa5\xcb\xd2\x19\x0f\xef\x7b\xee" +
+	"\x8f\xd3\x33\xbd\xc8\xe2\xeb\x7e\x60\xa1\x7d\xd2\x77\x5c\x91\x4e" +
+	"\xc9\x05\x38\x60\x79\x8f\xd3\x4b\xa9\x91\x49\x59\x2f\xb5\x6b\x60" +
+	"\x8d\x3b\xa1\x6b\x97\x4f\x98\xd9\x5d\x9e\x78\x79\x9e\x59\x2c\x06" +
+	"\x37\x03\xcb\xa2\x04\xa5\x18\x5d\xed\xee\x9c\x7a\x71\xdc\x6e\x7a" +
+	"\x7a\xc7\xeb\xe6\x3a\x5e\x9c\xda\x6a\xf6\xe3\x65\x5a\xa7\xd1\x64" +
+	"\x35\x13\xb7\x3b\x21\x15\xfd\x76\x58\x2e\x1e\x59\xa0\xed\xf3\xe3" +
+	"\x65\x40\x6a\x39\x96\x51\xd4\x46\x29\x0a\xac\x69\x0e\xb6\x7c\x81" +
+	"\xda\xd3\x36\x15\xd5\xfa\x35\x1f\xbc\xb3\x9b\xbb\xc5\xe6\x34\x5f" +
+	"\xf4\x56\x86\x57\xd7\xd1\x12\xb0\xe8\x2d\x5e\xde\xb3\x60\x1c\x1c" +
+	"\x27\x9d\x2e\xa7\xd1\x25\x26\x83\xbe\xb8\x8c\xb6\x13\x9e\xc2\x44" +
+	"\xc9\xc5\xcb\x4c\x4c\x17\xe8\xd0\x1f\xfb\xde\x42\xd9\x10\xbd\x1e" +
+	"\xc6\x73\xb5\x9a\x1c\x8b\x40\x09\x44\x21\x3a\xe4\x08\x70\x0c\x40" +
+	"\x6a\xc3\x85\x8a\xe0\xdc\x07\xc5\x17\x17\x06\x93\xb0\xf6\x06\xfa" +
+	"\x96\xcd\xe3\xb2\xf1\x44\xf3\xb9\x5f\x0e\x28\x09\x56\xdc\x56\x24" +
+	"\xe4\x6f\x43\x78\xe6\x88\xc7\xaa\x10\xba\xa2\xf3\xee\x16\x15\x54" +
+	"\x58\xa7\x60\xfd\x55\xff\x02\x73\x0c\xa7\x9c\x69\x14\x50\x08\xf6" +
+	"\x6b\x5e\x25\x1f\xfa\x0a\xc2\x3d\xd8\xfa\x08\x36\x67\xf0\x4f\x60" +
+	"\xe1\xd7\xc8\xd7\x3a\x5f\xba\x03\xd5\xd7\x03\x1a\x81\xf9\x4d\x69" +
+	"\xec\x83\xa3\xa5\x51\x97\x71\x5c\x7d\xc8\xdc\x60\xde\x7f\xc8\x14" +
+	"\x7e\xa0\x09\x59\x83\x3b\x8a\xd8\x77\x67\x0e\xb4\xf8\x1d\x81\xa1" +
+	"\xe6\x32\x82\xe5\x63\x61\x14\xcf\xbc\xbb\x0f\x02\x69\x40\xf5\x9d" +
+	"\x85\xfa\xfa\x6f\x5a\xf6\x3d\x31\x20\xd1\xcc\x67\xb6\xf0\xde\x54" +
+	"\xe2\x7f\x51\x2b\xbc\x05\xed\x07\xb6\x6f\x54\x51\x26\x91\xe0\xc8" +
+	"\xfb\xb8\x91\xaa\x49\x04\x2f\x9b\x82\x25\x87\x7c\x1e\xbb\x72\x55" +
+	"\xb4\x65\x34\x30\x83\x8c\xc9\xb1\x59\xa9\x71\xb1\x7a\xdc\x59\x34" +
+	"\x18\x42\x4c\x2c\xf7\xee\xb4\x2f\xa7\xdc\xaf\x95\x43\xec\x0f\x12" +
+	"\x88\x2e\x99\x92\x4e\xc9\xde\x29\x8d\xce\x24\xc9\xed\xe0\x83\x7c" +
+	"\x53\x37\xd1\x7a\xdd\xcb\xee\x60\x6d\xa2\x5e\x19\x26\xfe\x43\xe6" +
+	"\x53\x97\xcb\xc2\x92\x73\x14\xb8\xac\x6f\x6e\x62\x24\x51\x63\xef" +
+	"\x9e\x76\x27\x73\xb3\xb8\x2b\x78\x23\xd6\x89\xc5\xb1\x5e\x2e\x4f" +
+	"\x2c\x9e\x79\x75\xe3\x6f\x16\x37\x1a\x04\x9b\xba\xec\x1c\x57\xbe" +
+	"\x3d\xea\xc1\x7b\x22\xc1\xba\x49\xbe\x5a\xa6\x4a\xbc\x90\xe5\x72" +
+	"\x99\x9b\x6a\x80\x6e\x69\x3f\x77\x0e\x77\x67\xae\x9c\x79\xca\xaa" +
+	"\xd0\x9d\xe1\xdd\xec\xb4\x2c\x0e\x24\xaa\x42\x82\xe9\xba\x2b\x8b" +
+	"\xf5\xd3\xf3\xe3\x6b\x82\x77\x42\x2e\x55\xd3\xb0\xbe\x0f\x36\x3c" +
+	"\x88\x39\x9b\xa4\x63\x5e\xd9\xa7\xb3\xf4\xd0\x27\x3a\xed\x88\xb3" +
+	"\x35\x46\x63\x70\xf1\xa8\x43\xc3\x32\x8b\x0e\x38\xc3\xf4\xa0\x68" +
+	"\x12\xbc\x6d\x1f\x27\xea\x03\x39\x15\xba\x53\xeb\x10\x70\x7e\xcc" +
+	"\x12\xb9\x31\x6b\x39\x6c\x2f\x7e\x5c\xd5\x45\x5a\x2a\x68\x3d\x48" +
+	"\x8a\x5d\x57\xec\x2f\xe1\x33\xc0\xb1\xa5\xfe\x3a\xd4\xff\x0e\x00" +
+	"\x00\xff\xff\x8b\x62\x79\xeb\xf1\x05\x00\x00"
+
+// addTrustCrt returns raw, uncompressed file data.
+func addTrustCrt() []byte {
+	var empty [0]byte
+	sx := (*reflect.StringHeader)(unsafe.Pointer(&_addTrustCrt))
+	b := empty[:]
+	bx := (*reflect.SliceHeader)(unsafe.Pointer(&b))
+	bx.Data = sx.Data
+	bx.Len = len(_addTrustCrt)
+	bx.Cap = bx.Len
+
+	gz, err := gzip.NewReader(bytes.NewBuffer(b))
+
+	if err != nil {
+		panic("Decompression failed: " + err.Error())
+	}
+
+	var buf bytes.Buffer
+	io.Copy(&buf, gz)
+	gz.Close()
+
+	return buf.Bytes()
+}

+ 33 - 0
src/ngrok/client/tls/load.go

@@ -0,0 +1,33 @@
+package tls
+
+import (
+	"crypto/tls"
+	"crypto/x509"
+	"encoding/pem"
+)
+
+var (
+	Config *tls.Config
+)
+
+func init() {
+	pool := x509.NewCertPool()
+	for _, b := range [][]byte{ngrokRootCrt(), snakeoilCaCrt()} {
+		pemBlock, _ := pem.Decode(b)
+		if pemBlock == nil {
+			panic("Bad PEM data")
+		}
+
+		certs, err := x509.ParseCertificates(pemBlock.Bytes)
+		if err != nil {
+			panic(err)
+		}
+
+		pool.AddCert(certs[0])
+	}
+
+	Config = &tls.Config{
+		RootCAs:    pool,
+		ServerName: "tls.ngrok.com",
+	}
+}

+ 102 - 0
src/ngrok/client/tls/ngrokroot.crt.go

@@ -0,0 +1,102 @@
+package tls
+
+import (
+	"bytes"
+	"compress/gzip"
+	"io"
+	"reflect"
+	"unsafe"
+)
+
+var _ngrokRootCrt = "" +
+	"\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\x74\x94\x5b\xcf\xaa\x38" +
+	"\x14\x86\xef\xf9\x15\x73\x6f\x26\xa2\x82\xca\xc5\x5c\xb4\xa5\x40" +
+	"\xd1\x02\xe5\x28\xdc\x71\x12\x04\xf1\x88\x16\xf9\xf5\xe3\xe7\xb7" +
+	"\x33\xd9\x33\x7b\x76\x93\x26\xcd\xdb\x64\xad\xb7\x5d\xcf\x5a\x7f" +
+	"\x7e\x2d\x88\x75\x62\xfd\x81\xb0\xeb\x13\x8d\x20\xe0\xe3\x8f\x2a" +
+	"\x50\x42\xb0\xd5\x20\x04\x86\x65\x05\x38\x81\xa0\x7a\x6f\x1f\x58" +
+	"\xb0\x6a\xaf\x75\x7b\xd0\x15\x2e\x42\xc0\x02\x0d\xa8\xf0\x49\xd9" +
+	"\x9d\x23\x16\xab\x21\x63\x3a\xe6\xa6\xef\xfa\x38\x10\x28\x24\x3a" +
+	"\x98\x05\x18\xd5\x74\xcb\x22\xb7\x0d\x0d\x73\x96\x2f\x58\xc5\x02" +
+	"\x32\x98\x0d\x68\x61\x65\x85\x10\xdc\x7d\x23\xd0\xda\x44\x73\x5f" +
+	"\xc5\xce\x12\x09\x0e\xa5\x42\x0f\x5f\x59\xa7\xdd\x05\xa2\xb9\x41" +
+	"\x80\xa0\x9d\xec\xdc\x45\xb6\x30\x6f\xd4\x23\x9c\x80\x4f\x16\x15" +
+	"\x0f\x47\x98\xe8\x6e\x90\x9f\xc2\xb1\x40\x50\x2b\x0d\xf7\x98\x77" +
+	"\x72\x9d\x21\xa8\x32\x0f\x7a\xd9\x5c\x11\xdf\x0e\xa4\x9d\xea\x03" +
+	"\x4e\xd5\x60\xa4\x2a\xe6\x96\x5a\x8d\xb6\x76\x7e\x6b\xe4\xbf\x1a" +
+	"\xcf\x46\xbc\xa5\xa0\xfd\x38\x86\x35\x45\x81\x18\x0c\x82\xa6\x02" +
+	"\xef\xdb\xe6\xd9\x47\xe2\xcf\x36\x35\x44\xbd\x98\x9b\xdf\x6e\xb6" +
+	"\x78\x98\xfd\xaf\x1b\xe1\x6d\x27\x08\x35\x50\xf9\x5d\x28\x16\x73" +
+	"\xe5\x95\x8e\xf8\x40\x11\xf8\x64\x01\x03\x4d\x7e\xfe\x17\x77\x57" +
+	"\x8b\xc9\xce\x7c\xc4\x11\xaf\x98\x88\xab\xa0\x53\x9e\x42\xa1\xbe" +
+	"\x2b\xf0\x7e\xb7\xca\x62\x73\x73\x4e\x48\xfd\xcc\x2d\xc0\x30\x84" +
+	"\x0c\xa8\x55\x85\x1d\xf0\x75\xcf\xce\xe8\x7d\x86\x60\xbb\x5f\xe8" +
+	"\x8d\xd3\xad\x2b\x80\xb7\xfe\xa9\xf2\x8f\xcf\x5e\x30\x56\xc3\x5d" +
+	"\x5d\xcf\x67\x93\x83\x3d\x1f\xfb\x65\x86\x7d\x7b\x77\x41\x47\xba" +
+	"\x4f\xec\xfd\x33\xb8\xae\xdb\x89\xa8\xea\x0f\xdb\x19\x27\x61\x1f" +
+	"\x68\xb7\xe8\xf8\xea\x82\xe8\x8c\xb8\xb7\xbb\x65\xdb\xcb\x4e\x11" +
+	"\x1e\xf4\x3a\xb5\xc6\xaa\x37\x9a\xa5\xcb\xd2\x19\x0f\xef\x7b\xee" +
+	"\x8f\xd3\x33\xbd\xc8\xe2\xeb\x7e\x60\xa1\x7d\xd2\x77\x5c\x91\x4e" +
+	"\xc9\x05\x38\x60\x79\x8f\xd3\x4b\xa9\x91\x49\x59\x2f\xb5\x6b\x60" +
+	"\x8d\x3b\xa1\x6b\x97\x4f\x98\xd9\x5d\x9e\x78\x79\x9e\x59\x2c\x06" +
+	"\x37\x03\xcb\xa2\x04\xa5\x18\x5d\xed\xee\x9c\x7a\x71\xdc\x6e\x7a" +
+	"\x7a\xc7\xeb\xe6\x3a\x5e\x9c\xda\x6a\xf6\xe3\x65\x5a\xa7\xd1\x64" +
+	"\x35\x13\xb7\x3b\x21\x15\xfd\x76\x58\x2e\x1e\x59\xa0\xed\xf3\xe3" +
+	"\x65\x40\x6a\x39\x96\x51\xd4\x46\x29\x0a\xac\x69\x0e\xb6\x7c\x81" +
+	"\xda\xd3\x36\x15\xd5\xfa\x35\x1f\xbc\xb3\x9b\xbb\xc5\xe6\x34\x5f" +
+	"\xf4\x56\x86\x57\xd7\xd1\x12\xb0\xe8\x2d\x5e\xde\xb3\x60\x1c\x1c" +
+	"\x27\x9d\x2e\xa7\xd1\x25\x26\x83\xbe\xb8\x8c\xb6\x13\x9e\xc2\x44" +
+	"\xc9\xc5\xcb\x4c\x4c\x17\xe8\xd0\x1f\xfb\xde\x42\xd9\x10\xbd\x1e" +
+	"\xc6\x73\xb5\x9a\x1c\x8b\x40\x09\x44\x21\x3a\xe4\x08\x70\x0c\x40" +
+	"\x6a\xc3\x85\x8a\xe0\xdc\x07\xc5\x17\x17\x06\x93\xb0\xf6\x06\xfa" +
+	"\x96\xcd\xe3\xb2\xf1\x44\xf3\xb9\x5f\x0e\x28\x09\x56\xdc\x56\x24" +
+	"\xe4\x6f\x43\x78\xe6\x88\xc7\xaa\x10\xba\xa2\xf3\xee\x16\x15\x54" +
+	"\x58\xa7\x60\xfd\x55\xff\x02\x73\x0c\xa7\x9c\x69\x14\x50\x08\xf6" +
+	"\x6b\x5e\x25\x1f\xfa\x0a\xc2\x3d\xd8\xfa\x08\x36\x67\xf0\x4f\x60" +
+	"\xe1\xd7\xc8\xd7\x3a\x5f\xba\x03\xd5\xd7\x03\x1a\x81\xf9\x4d\x69" +
+	"\xec\x83\xa3\xa5\x51\x97\x71\x5c\x7d\xc8\xdc\x60\xde\x7f\xc8\x14" +
+	"\x7e\xa0\x09\x59\x83\x3b\x8a\xd8\x77\x67\x0e\xb4\xf8\x1d\x81\xa1" +
+	"\xe6\x32\x82\xe5\x63\x61\x14\xcf\xbc\xbb\x0f\x02\x69\x40\xf5\x9d" +
+	"\x85\xfa\xfa\x6f\x5a\xf6\x3d\x31\x20\xd1\xcc\x67\xb6\xf0\xde\x54" +
+	"\xe2\x7f\x51\x2b\xbc\x05\xed\x07\xb6\x6f\x54\x51\x26\x91\xe0\xc8" +
+	"\xfb\xb8\x91\xaa\x49\x04\x2f\x9b\x82\x25\x87\x7c\x1e\xbb\x72\x55" +
+	"\xb4\x65\x34\x30\x83\x8c\xc9\xb1\x59\xa9\x71\xb1\x7a\xdc\x59\x34" +
+	"\x18\x42\x4c\x2c\xf7\xee\xb4\x2f\xa7\xdc\xaf\x95\x43\xec\x0f\x12" +
+	"\x88\x2e\x99\x92\x4e\xc9\xde\x29\x8d\xce\x24\xc9\xed\xe0\x83\x7c" +
+	"\x53\x37\xd1\x7a\xdd\xcb\xee\x60\x6d\xa2\x5e\x19\x26\xfe\x43\xe6" +
+	"\x53\x97\xcb\xc2\x92\x73\x14\xb8\xac\x6f\x6e\x62\x24\x51\x63\xef" +
+	"\x9e\x76\x27\x73\xb3\xb8\x2b\x78\x23\xd6\x89\xc5\xb1\x5e\x2e\x4f" +
+	"\x2c\x9e\x79\x75\xe3\x6f\x16\x37\x1a\x04\x9b\xba\xec\x1c\x57\xbe" +
+	"\x3d\xea\xc1\x7b\x22\xc1\xba\x49\xbe\x5a\xa6\x4a\xbc\x90\xe5\x72" +
+	"\x99\x9b\x6a\x80\x6e\x69\x3f\x77\x0e\x77\x67\xae\x9c\x79\xca\xaa" +
+	"\xd0\x9d\xe1\xdd\xec\xb4\x2c\x0e\x24\xaa\x42\x82\xe9\xba\x2b\x8b" +
+	"\xf5\xd3\xf3\xe3\x6b\x82\x77\x42\x2e\x55\xd3\xb0\xbe\x0f\x36\x3c" +
+	"\x88\x39\x9b\xa4\x63\x5e\xd9\xa7\xb3\xf4\xd0\x27\x3a\xed\x88\xb3" +
+	"\x35\x46\x63\x70\xf1\xa8\x43\xc3\x32\x8b\x0e\x38\xc3\xf4\xa0\x68" +
+	"\x12\xbc\x6d\x1f\x27\xea\x03\x39\x15\xba\x53\xeb\x10\x70\x7e\xcc" +
+	"\x12\xb9\x31\x6b\x39\x6c\x2f\x7e\x5c\xd5\x45\x5a\x2a\x68\x3d\x48" +
+	"\x8a\x5d\x57\xec\x2f\xe1\x33\xc0\xb1\xa5\xfe\x3a\xd4\xff\x0e\x00" +
+	"\x00\xff\xff\x8b\x62\x79\xeb\xf1\x05\x00\x00"
+
+// ngrokRootCrt returns raw, uncompressed file data.
+func ngrokRootCrt() []byte {
+	var empty [0]byte
+	sx := (*reflect.StringHeader)(unsafe.Pointer(&_ngrokRootCrt))
+	b := empty[:]
+	bx := (*reflect.SliceHeader)(unsafe.Pointer(&b))
+	bx.Data = sx.Data
+	bx.Len = len(_ngrokRootCrt)
+	bx.Cap = bx.Len
+
+	gz, err := gzip.NewReader(bytes.NewBuffer(b))
+
+	if err != nil {
+		panic("Decompression failed: " + err.Error())
+	}
+
+	var buf bytes.Buffer
+	io.Copy(&buf, gz)
+	gz.Close()
+
+	return buf.Bytes()
+}

+ 121 - 0
src/ngrok/client/tls/snakeoilca.crt.go

@@ -0,0 +1,121 @@
+package tls
+
+import (
+	"bytes"
+	"compress/gzip"
+	"io"
+	"reflect"
+	"unsafe"
+)
+
+var _snakeoilCaCrt = "" +
+	"\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\x6c\x95\xc7\x0e\xab\xce" +
+	"\x92\xc6\xf7\x3c\xc5\xec\xd1\x08\x0c\x26\x2d\x66\xd1\x34\x4d\x06" +
+	"\x93\x31\xec\x8c\x03\x98\x9c\xd3\xd3\x8f\xff\xe7\x48\x23\xcd\xbd" +
+	"\xb7\x57\xad\xaf\x5a\xbf\x2e\x95\xea\xab\xfa\xef\x7f\x8e\x88\x14" +
+	"\xcd\xfe\x2f\x88\xbc\x40\x93\x35\x08\x02\xf4\x47\xc5\x2c\x4d\x93" +
+	"\x65\x09\x42\xb0\x6e\x10\xba\xb0\xca\x6c\xd2\x53\x88\xee\xc2\x48" +
+	"\xc0\x16\xf3\x6a\x28\xaa\xaf\x22\x6c\xa4\x08\xdc\x50\x06\x92\x68" +
+	"\x59\xee\xb4\x41\x37\x91\x22\xd7\x55\xd0\xa6\x47\x58\x78\xa2\xc0" +
+	"\xfa\xc1\xc1\x25\x44\x50\xb4\x0c\x97\x92\xa7\x47\x9c\xae\xcf\x86" +
+	"\xe9\x93\x00\xf9\x96\x08\xfe\xc6\x0a\x4b\xcf\x9a\xd7\x91\x51\xd3" +
+	"\x92\x50\xc2\x6c\x79\xee\x86\xf2\x44\xc2\x7e\x24\x49\x06\xd3\x60" +
+	"\x36\x4c\xfb\x6c\x84\xd1\x6c\xec\x35\x0b\xc0\x5b\xde\xc8\xdd\x3a" +
+	"\x01\x65\x49\xd6\x66\x9d\xe1\x6e\x07\xe9\xe3\xa7\x1d\x7f\x35\xf4" +
+	"\x7f\x1a\x66\xa1\x6d\x87\x27\xd0\xc5\xdc\x8e\x44\x90\x04\xa0\x8e" +
+	"\x02\xcb\xb3\x36\xf4\x37\x4d\x0d\x6d\xbd\x94\xc4\x7b\x9f\x36\xc2" +
+	"\x91\x35\x75\x61\x79\xda\x86\xc0\x9f\x98\x81\xb6\x7a\xc1\x52\x5a" +
+	"\x5f\x1f\x07\x53\x66\x14\xb9\xcb\x12\xf0\xff\x82\xac\x10\x1e\xdd" +
+	"\xf2\xff\x52\xd6\x34\xa8\x95\xff\x5a\x17\x24\x63\x00\xdc\x20\xc8" +
+	"\x79\xf0\xcf\x03\x98\x1b\xbf\x3b\x02\xac\x3b\x1e\xf7\xb7\x51\xf3" +
+	"\x20\x8e\x1f\xc2\xa2\x50\x61\xe6\xdf\xfa\xae\x53\xb9\xeb\x69\x56" +
+	"\xf7\x89\x96\xd3\x4f\x25\xe4\xc6\x3a\x54\x5f\xec\xbc\xdf\x5d\xe8" +
+	"\x35\x73\xc8\x4a\x47\x4b\xe2\xb7\xc5\xa7\x27\x44\x8c\x5e\x93\x82" +
+	"\xc9\x2f\x2b\x57\x21\x12\x69\x7e\x21\xc2\xcf\xcd\xeb\x2b\x62\x7d" +
+	"\x96\x1a\xbe\x6e\x9b\x3b\x5d\x55\x7a\x64\xe8\x17\x98\x03\xaf\xea" +
+	"\x96\xf1\x41\x69\x09\x31\x03\x5f\x78\xb7\x45\xa7\xe5\x92\x6b\x4d" +
+	"\x82\xa4\x70\x2b\x3e\x79\x12\xe4\x7a\xc7\x4f\xe9\xb6\x35\x5e\xac" +
+	"\x94\xb6\xe1\x0c\x57\x8a\x5a\x26\x59\x80\xba\xfc\x24\x30\xde\x4d" +
+	"\xf0\x9b\xa4\x4b\xea\xd2\xf2\x51\x04\xaa\x81\xbe\x7f\x9e\xce\x3d" +
+	"\x3f\x66\x55\x1b\xf6\xd5\xd7\xdb\x24\x97\xba\x45\x86\x00\x57\x82" +
+	"\xc9\xe8\x09\x96\xf1\x99\xe7\x37\xf7\x6b\x6d\x74\xd3\x4c\xc5\x38" +
+	"\x8e\x79\x06\x71\x01\xcb\x35\x69\x07\x36\x3f\x8f\xb1\xa2\xbd\xaf" +
+	"\xf2\xca\x2e\x9a\xb2\x68\xfa\x67\xb6\xf4\x7d\xd1\x0f\x3d\xca\x3e" +
+	"\x81\x3c\x0f\xb9\xa5\x04\x4d\xa9\xa6\xfb\xd7\x5c\x2d\xee\x75\x72" +
+	"\x58\x49\x64\xcd\x78\x5e\x9d\xb5\x2d\x32\xd7\x4f\x53\xb3\x98\x56" +
+	"\xe7\xd2\xf1\xcd\xde\x76\xb6\xd5\x77\x44\xd0\x31\xb3\xda\x13\xc1" +
+	"\xc4\x66\x8c\xec\xda\x26\x27\xab\x7d\x73\x8b\x4c\xd0\xb9\xb4\xfc" +
+	"\xba\x63\xd1\x78\x04\x65\xe7\x97\x5f\x44\xeb\xa6\xa4\xa4\x9a\xed" +
+	"\x0a\x96\x8c\x9c\xdc\x39\x3d\xfe\x87\x1e\xe4\x8e\x60\xdf\xdc\x22" +
+	"\x5e\x41\x52\x1b\x9d\xdb\x91\x17\xe3\xdc\xf1\xa4\x89\x36\xcf\x40" +
+	"\xf3\x88\x45\x30\xf0\x52\xef\x59\xb3\x2c\x9e\x5b\xd5\xf3\x4e\x8e" +
+	"\x47\x17\xb5\x79\x5e\x6a\x71\xbc\x5c\x5f\xfc\x02\x0a\xba\xfc\xe0" +
+	"\xb8\xf1\x22\xa5\x32\x23\x6a\x4e\x82\x4e\x8f\x72\x5f\xdf\xd2\x24" +
+	"\x28\xa1\x89\xa5\xac\xbf\x7f\xc5\xcd\xbd\x76\xc2\x0b\xb9\x8f\x97" +
+	"\xa5\xe4\x15\x3d\xd7\x92\x0c\xc5\x69\x54\xbb\x81\xb3\x8f\x73\xbd" +
+	"\xab\x0e\x29\xca\x94\x6a\x64\xbc\xe1\x21\x11\x19\x50\x5b\xdc\x52" +
+	"\xf0\x60\x11\x63\x39\xc9\x9d\xcd\xad\x2f\xdb\x3c\x9e\x48\x78\x7f" +
+	"\x24\xf5\x81\x07\x92\x83\x33\x52\x0a\x2d\x45\x12\xaa\xe6\x5e\xb9" +
+	"\x89\x30\x10\xe7\x30\xac\xd6\x8c\x07\x38\x11\x88\x86\x50\x6f\xe1" +
+	"\xd4\x7d\xa9\xf0\x89\xad\x02\xbd\xf9\x78\x60\x2f\x24\xfb\xf0\xba" +
+	"\x7e\x70\x3a\x21\x49\x47\x9a\xaf\x1e\xf4\x6e\x38\xdf\x9b\xc0\x5e" +
+	"\xfb\x8a\x12\x3b\xd9\x66\xb8\x9c\x63\x39\x85\xaf\x84\x20\x2b\x2a" +
+	"\x71\xff\xce\xab\x1c\x42\x0c\xfc\xac\x01\x82\xff\xe0\xfd\x3f\x2d" +
+	"\x8e\x80\xf7\x21\x8a\x28\x69\xe7\x33\xdc\xe4\x30\x77\xc7\x58\x22" +
+	"\x6b\x22\x7c\x40\x31\x1f\xeb\x75\x8f\x20\x76\x84\x0f\x5e\x9b\x4a" +
+	"\x7a\x7d\x9f\xa0\x90\xfd\x23\x6d\x67\x64\xe2\xc8\x94\x57\x7e\x5d" +
+	"\xdd\x6c\x16\x15\x55\x25\x66\xd8\x72\x6c\xbc\x0c\xe5\x76\x2b\x23" +
+	"\x93\xa2\x8f\xbd\x7a\xe8\xd3\xd8\x7a\x02\x8e\x05\x9e\x2d\xb7\xd1" +
+	"\x5b\xe4\x2f\x0c\x87\x6b\x32\xab\x1a\xa7\x09\x4d\x42\xd5\xc0\xd7" +
+	"\x25\xab\x8d\xa0\x6e\xbe\xf9\xfb\x34\x6d\x41\x95\x53\x57\x40\x12" +
+	"\x82\xaf\x3e\x7b\x8d\x51\x00\x19\xd7\x41\x81\xb0\xab\x32\xe4\xcf" +
+	"\xf0\x6b\x0b\x0d\xde\x98\x7c\x19\x2b\x74\x5e\xe2\xfe\x1d\x72\xda" +
+	"\x33\xf2\xe9\x15\xac\xfe\x45\xe7\x8c\x93\xb4\xcf\xa0\xb8\xbc\x92" +
+	"\xca\xb5\x63\xbd\x7e\x2c\x37\xca\x6d\x05\x26\x10\x04\xac\xaf\x2b" +
+	"\xc7\x29\x78\xee\x48\x6f\xc2\x43\xc8\xf6\xfe\x2e\x38\xa1\x5e\x05" +
+	"\xfa\x79\xdb\xc2\x2a\xd5\x7c\x2f\x45\xbf\x09\x45\xc2\xcf\xd4\x87" +
+	"\xfd\x40\xf4\xc5\xb9\x04\xd1\xf7\xe0\x3a\xea\x33\xe2\x41\x87\xed" +
+	"\x51\xf4\xa0\x1e\x46\x20\x5c\xa8\xb5\xfe\xf5\x41\xbc\x31\xdd\x80" +
+	"\x0c\x6e\x3f\xf6\x60\x98\x92\x2d\xe2\x60\x58\x97\xbf\x22\x14\xbd" +
+	"\xcf\x6d\xb7\xb4\xd8\x4e\x8d\x1e\xc2\x4a\x50\x0d\x95\xf4\x66\x01" +
+	"\x23\x54\x77\x02\xf6\xe2\x7f\xab\xb4\x9b\xec\xf5\x65\xd1\x44\xb1" +
+	"\xd2\x4f\x46\xf2\xc2\xdb\x66\x7c\x8d\x57\x96\xa7\xf0\x18\xdc\x0f" +
+	"\x7f\xf7\xdf\xba\x67\x5d\xbe\xee\xfa\x54\x3b\x3e\xe4\x2b\xa4\x23" +
+	"\x34\x63\xaf\xe6\x33\xb7\x38\x99\xab\xb4\xe7\x4c\x11\x49\xf1\x38" +
+	"\x77\x97\xd8\x6d\x7c\x0c\x9f\xe7\xcf\x6d\xf6\x69\xb6\x03\x35\x4a" +
+	"\xa6\x0f\x3e\x0a\x1d\x70\x7d\x4f\xb6\x17\x41\x3f\xc2\xef\x3b\x9e" +
+	"\x02\xef\xca\x60\xbd\xf2\xdc\xec\xfe\x2e\x55\xf8\xf6\x1e\x5c\xa3" +
+	"\x6a\xb7\xcc\xee\x8a\x07\xdd\x31\x97\xfb\x40\x5c\xda\xc2\x9b\x87" +
+	"\x31\x74\x34\x94\xdf\x5a\x31\x16\x61\xc4\xaf\x55\x71\xb7\x0a\x21" +
+	"\xca\xde\x78\x07\x1a\xcc\x6c\xb6\xb7\x7d\xb1\x46\xd6\x2a\x47\x35" +
+	"\x7e\xbd\xa2\x16\xd7\x95\xa7\xc8\xf4\x38\xb0\xe2\x91\x3f\x11\x9e" +
+	"\x15\xbd\x03\x41\xbb\xf4\xb2\x27\xf0\x27\xfd\xc9\x6e\xf5\xdb\x82" +
+	"\xf1\xc0\xba\x78\x61\x39\x98\x15\x06\xc5\xa0\x7b\x37\xf5\xd1\xa8" +
+	"\x9e\xa6\xd3\xda\xc9\x6f\x85\x36\x96\x1c\x32\x2a\x49\x34\x4c\xf4" +
+	"\x41\x17\xb4\xfb\xb4\x28\x44\x2e\x9e\xbc\xd4\x83\x9d\xca\xf7\xfe" +
+	"\x6a\xa0\xe6\xe6\xa8\x1e\xae\xd8\xd5\xb7\x96\x84\xd0\xab\xb4\xee" +
+	"\xfe\x07\xfb\xb3\xed\x90\x2d\xfd\xfb\x06\xfc\xdf\x00\x00\x00\xff" +
+	"\xff\x92\x24\xb8\x34\x1e\x07\x00\x00"
+
+// snakeoilCaCrt returns raw, uncompressed file data.
+func snakeoilCaCrt() []byte {
+	var empty [0]byte
+	sx := (*reflect.StringHeader)(unsafe.Pointer(&_snakeoilCaCrt))
+	b := empty[:]
+	bx := (*reflect.SliceHeader)(unsafe.Pointer(&b))
+	bx.Data = sx.Data
+	bx.Len = len(_snakeoilCaCrt)
+	bx.Cap = bx.Len
+
+	gz, err := gzip.NewReader(bytes.NewBuffer(b))
+
+	if err != nil {
+		panic("Decompression failed: " + err.Error())
+	}
+
+	var buf bytes.Buffer
+	io.Copy(&buf, gz)
+	gz.Close()
+
+	return buf.Bytes()
+}

+ 11 - 4
src/ngrok/conn/conn.go

@@ -3,6 +3,7 @@ package conn
 import (
 	"bufio"
 	"bytes"
+	"crypto/tls"
 	"fmt"
 	"io"
 	"math/rand"
@@ -35,7 +36,7 @@ func wrapTcpConn(conn net.Conn, typ string) *tcpConn {
 	return c
 }
 
-func Listen(addr *net.TCPAddr, typ string) (l *Listener, err error) {
+func Listen(addr *net.TCPAddr, typ string, tlsCfg *tls.Config) (l *Listener, err error) {
 	// listen for incoming connections
 	listener, err := net.ListenTCP("tcp", addr)
 	if err != nil {
@@ -56,6 +57,9 @@ func Listen(addr *net.TCPAddr, typ string) (l *Listener, err error) {
 			}
 
 			c := wrapTcpConn(tcpConn, typ)
+			if tlsCfg != nil {
+				c.Conn = tls.Server(c.Conn, tlsCfg)
+			}
 			c.Info("New connection from %v", tcpConn.RemoteAddr())
 			l.Conns <- c
 		}
@@ -67,21 +71,24 @@ func Wrap(conn net.Conn, typ string) *tcpConn {
 	return wrapTcpConn(conn, typ)
 }
 
-func Dial(addr, typ string) (conn *tcpConn, err error) {
+func Dial(addr, typ string, tlsCfg *tls.Config) (conn *tcpConn, err error) {
 	var (
 		tcpAddr *net.TCPAddr
-		tcpConn *net.TCPConn
+		tcpConn net.Conn
 	)
 
 	if tcpAddr, err = net.ResolveTCPAddr("tcp", addr); err != nil {
 		return
 	}
 
-	//log.Debug("Dialing %v", addr)
 	if tcpConn, err = net.DialTCP("tcp", nil, tcpAddr); err != nil {
 		return
 	}
 
+	if tlsCfg != nil {
+		tcpConn = tls.Client(tcpConn, tlsCfg)
+	}
+
 	conn = wrapTcpConn(tcpConn, typ)
 	conn.Debug("New connection to: %v", tcpAddr)
 	return conn, nil

+ 1 - 1
src/ngrok/server/http.go

@@ -33,7 +33,7 @@ Bad Request
  */
 func httpListener(addr *net.TCPAddr) {
 	// bind/listen for incoming connections
-	listener, err := conn.Listen(addr, "pub")
+	listener, err := conn.Listen(addr, "pub", nil)
 	if err != nil {
 		panic(err)
 	}

+ 4 - 3
src/ngrok/server/main.go

@@ -7,6 +7,7 @@ import (
 	"ngrok/conn"
 	log "ngrok/log"
 	"ngrok/msg"
+	"ngrok/server/tls"
 	"regexp"
 )
 
@@ -31,7 +32,7 @@ func init() {
 
 func parseArgs() *Options {
 	publicPort := flag.Int("publicport", 80, "Public port")
-	tunnelPort := flag.Int("tunnelport", 2280, "Tunnel port")
+	tunnelPort := flag.Int("tunnelport", 4443, "Tunnel port")
 	proxyPort := flag.Int("proxyPort", 0, "Proxy port")
 	domain := flag.String("domain", "ngrok.com", "Domain where the tunnels are hosted")
 	logto := flag.String(
@@ -55,7 +56,7 @@ func parseArgs() *Options {
  */
 func controlListener(addr *net.TCPAddr, domain string) {
 	// listen for incoming connections
-	listener, err := conn.Listen(addr, "ctl")
+	listener, err := conn.Listen(addr, "ctl", tls.Config)
 	if err != nil {
 		panic(err)
 	}
@@ -70,7 +71,7 @@ func controlListener(addr *net.TCPAddr, domain string) {
  * Listens for new proxy connections from tunnel clients
  */
 func proxyListener(addr *net.TCPAddr, domain string) {
-	listener, err := conn.Listen(addr, "pxy")
+	listener, err := conn.Listen(addr, "pxy", tls.Config)
 	if err != nil {
 		panic(err)
 	}

+ 38 - 0
src/ngrok/server/tls/load.go

@@ -0,0 +1,38 @@
+package tls
+
+import (
+	"crypto/tls"
+	"io/ioutil"
+	"os"
+)
+
+var (
+	Config *tls.Config
+)
+
+func init() {
+	readOrBytes := func(envVar string, defaultFile func() []byte) []byte {
+		f := os.Getenv(envVar)
+		if f == "" {
+			return defaultFile()
+		} else {
+			if b, err := ioutil.ReadFile(f); err != nil {
+				panic(err)
+			} else {
+				return b
+			}
+		}
+	}
+
+	crt := readOrBytes("TLS_CRT_FILE", snakeoilCrt)
+	key := readOrBytes("TLS_KEY_FILE", snakeoilKey)
+	cert, err := tls.X509KeyPair(crt, key)
+
+	if err != nil {
+		panic(err)
+	}
+
+	Config = &tls.Config{
+		Certificates: []tls.Certificate{cert},
+	}
+}

+ 120 - 0
src/ngrok/server/tls/snakeoil.crt.go

@@ -0,0 +1,120 @@
+package tls
+
+import (
+	"bytes"
+	"compress/gzip"
+	"io"
+	"reflect"
+	"unsafe"
+)
+
+var _snakeoilCrt = "" +
+	"\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\x64\x55\xc7\x0e\xab\xda" +
+	"\x96\x9c\xf3\x15\x3d\x47\x2d\x32\xb6\x87\xc0\x26\xb3\xc9\x06\xc3" +
+	"\x8c\x9c\xb3\x31\x98\xaf\x6f\x9f\x73\xa5\xd6\xd3\x7d\xcc\x56\x2d" +
+	"\xa9\xa8\x5d\xaa\xd2\xfa\xdf\x3f\x1f\x2f\xca\xaa\xf9\x3f\x82\xe8" +
+	"\xfa\xaa\xa4\x0a\x9c\x2f\xfe\x45\x11\xa8\xaa\x12\x00\x82\xc0\x7d" +
+	"\x1c\x81\x73\xc4\x03\x38\x91\xa6\x4f\xb1\x5a\x7f\x32\xf3\x37\x4b" +
+	"\xbc\xc3\x1d\x3e\x10\x0d\xc8\x75\x32\x47\x3c\x45\xbe\x86\x42\x10" +
+	"\xc0\x53\xbc\x38\x97\xaf\xcc\x00\xe1\xb9\xca\x17\x3a\xb3\x4e\xe5" +
+	"\x7e\x48\x29\x6d\x4f\x42\xf1\x14\x5b\xce\xf9\xb3\xe4\xb9\xc9\x17" +
+	"\x42\x66\xcc\x86\xc7\x6a\x0c\xe6\x27\xf5\xc5\x27\xe4\xd5\xbf\x44" +
+	"\xdc\xe9\x18\x7a\xc3\xec\x48\x4c\x69\x9f\xe4\xcb\xb4\x29\x89\x1f" +
+	"\x4a\x9d\x99\xd0\x87\x87\xd9\x72\x17\x04\xce\x17\x5e\xdc\x11\xfe" +
+	"\xc1\xda\xbf\xd8\xf9\xff\x58\xcb\x43\xe8\x6c\x87\xe0\x44\x00\x09" +
+	"\x1c\x47\x16\x0f\x2d\x78\x5e\xa2\x0f\x7f\xcf\xfc\xc3\x2e\xf0\x50" +
+	"\x77\x48\x69\x4b\xc2\xf8\x93\x0d\xcc\x1c\xf9\xa2\x07\x79\xee\x9f" +
+	"\x5d\x0d\xb5\x74\xc8\xbf\x29\xb9\xed\x11\xf9\x78\x23\xd0\x75\x0e" +
+	"\xb1\x8a\xc0\x8f\x08\x48\xdc\xb6\x18\xc3\x7f\x4a\xfe\x79\xd3\xa8" +
+	"\xff\xf6\x85\xff\xf9\x02\xaa\x4a\xb5\xb9\x9f\x77\x08\x57\x4d\xc2" +
+	"\x6f\xe0\x39\x73\xda\x5f\x02\x7b\x68\x49\x66\xab\x52\x24\x36\xba" +
+	"\x2a\xcb\x75\xdf\x78\xf5\xb9\x7d\x89\x3b\x61\x68\x38\x4b\xc7\x3e" +
+	"\xa0\x38\x17\xfa\xcd\xc3\x32\xad\xcd\xed\x94\x97\x8f\x4c\x10\x17" +
+	"\x02\x22\x36\xc1\xd8\xd8\x33\xa5\xa9\x46\x23\x1b\x0c\x29\xd9\x33" +
+	"\x5e\xe7\x5a\x51\x39\xe8\x7c\x5d\x58\x05\xda\x17\x5e\x3f\xa0\x10" +
+	"\x16\x27\xa4\x7f\x32\xe7\x08\xf7\x4b\x71\xe9\x1e\x3d\xa2\x84\xba" +
+	"\xad\x55\xa8\x05\xf4\xfb\x91\x10\xd8\xb1\x3b\x96\x8e\xa2\x03\xf6" +
+	"\x8a\xa8\x23\x4b\xe3\xca\x68\x49\x4a\x54\x32\xf9\x9b\xf6\xd8\x29" +
+	"\x6b\x5d\x52\x24\x8b\x6c\x7e\x56\x6d\xc2\x68\xb7\xf2\x0c\x04\x6b" +
+	"\xfd\x79\xc6\x73\x10\xea\xcf\x41\xe7\x67\x5f\xa1\xed\x1d\xb0\x69" +
+	"\xd7\xdf\x17\xdd\xe1\x6c\xa2\xd8\x7b\x36\xf6\x50\x79\xc5\xfa\x5e" +
+	"\x8a\xb4\x70\x39\xaa\x9c\xf2\x00\x15\xd6\x18\x4b\x44\xf4\x88\xb0" +
+	"\x1b\xd8\xb7\x62\x20\x4d\xa7\x7f\x8f\xbd\x74\x14\x4c\xe0\x11\x46" +
+	"\x39\xcd\xc1\xdb\xa2\x0a\xd2\x64\xca\x4f\x21\x3e\xf3\xb4\x22\x23" +
+	"\xb0\xdd\x8a\x8f\x19\x05\x3a\x4a\x34\x78\xd7\x4e\xbf\xdf\x52\x00" +
+	"\x79\xa7\x43\x5d\x10\x94\xe5\x60\x69\xb2\x97\x67\xa6\x64\xc4\xd9" +
+	"\xbe\xe5\x4d\x63\x6e\xc7\x76\x1f\x0b\xdb\xa0\x8b\x09\xfd\x48\x3b" +
+	"\x60\x9c\x36\x7b\x88\x5e\x79\xed\xa3\x57\x0c\x78\x2d\x30\x9c\x56" +
+	"\x49\xc8\xba\x85\x97\x1a\x6d\xeb\xed\xb9\x35\xbb\x2e\xd3\x95\x93" +
+	"\x03\xe2\x66\xa0\x60\xaa\x02\x61\x71\xb3\x3c\x7a\xed\xd5\x6a\x8b" +
+	"\x9a\x65\x36\xf7\x48\xa6\x0a\xd7\xb5\x31\xe7\xd1\xf5\x2f\xda\x0e" +
+	"\xbf\x37\x0b\x89\xdb\x9b\xfe\xc2\x4e\x7e\xfd\x78\x8c\x5c\x00\x73" +
+	"\x59\x41\xb0\xd9\x06\x1e\x92\xb4\xa4\x61\x98\xb7\x6f\x37\xde\x93" +
+	"\xf0\x32\x63\x80\x17\x2d\x6f\x40\xc7\x55\x49\xc8\x6e\x83\xa3\xa7" +
+	"\x97\x50\xc3\xe3\x97\x03\xed\x08\x2d\x65\x60\x1b\x01\x1f\x94\x23" +
+	"\xcf\xa7\xcb\x36\x72\x54\xb0\x31\x78\xb3\xa3\xcb\x76\x41\x13\x46" +
+	"\x58\x51\x4f\x82\xd4\x2c\x2e\x57\xf5\x91\x85\x0f\xb5\xfe\xd5\x3e" +
+	"\x93\x6f\xb5\x0b\x8b\xf8\x7c\x14\xcd\xd8\xdd\xc8\xd2\xa5\x5c\x9e" +
+	"\x9d\xca\x02\x6f\x8c\xc9\xd2\xcc\x5f\x3a\xf8\x36\x2b\xf4\x2c\x9f" +
+	"\xd6\x89\xbd\x22\xa0\x92\x2c\xf7\x29\xdd\x33\x63\x39\x51\x46\x69" +
+	"\x0a\x26\x67\x05\xdd\x45\xaa\xd1\x24\x98\x4d\x3b\x64\x5d\xfd\x92" +
+	"\xb7\xb2\x62\x0d\xee\x6a\x08\x39\xdc\x85\x2b\x26\x3a\x65\x69\x77" +
+	"\xa7\xa6\xa6\xa0\xdc\x79\x7d\x94\xca\x2d\x37\x9e\xa3\xc4\x55\xbf" +
+	"\x66\x70\xff\x54\x1f\xf9\x57\xf7\xc1\xdf\x58\x83\xa4\xe8\x49\xd4" +
+	"\x73\xef\x86\xc0\x9c\xa6\xc0\x67\x3b\x5d\x2c\x43\xd3\x53\x78\x58" +
+	"\xa7\xb7\x65\x59\x09\x56\x54\x9e\x18\xf4\x9c\x14\x19\x07\x09\x9e" +
+	"\xfc\xe2\x27\x24\x7f\x77\x41\xac\xaa\x5d\x7a\x33\xf6\x4e\xb9\xaf" +
+	"\x1b\x97\x3f\xef\xfc\xd5\x65\xe4\xd7\xcd\xdb\x89\x2b\x45\x08\x33" +
+	"\x8d\xc3\x4a\x38\x1f\x7b\xf2\x52\x99\x6c\x4f\xf4\x00\x69\xf2\x58" +
+	"\x9a\xcd\xe7\xd7\x45\x75\xe6\x29\x63\xc2\xf8\xce\x84\xcf\x71\xc5" +
+	"\x33\x8d\x61\x15\x6a\x04\xfa\x63\xb1\x41\x4c\xf2\xda\xc0\x61\x36" +
+	"\x74\x59\x6b\xae\xdd\xc3\x3d\x64\x74\xdd\x3d\xe3\x29\x34\xc8\xf7" +
+	"\xa8\x24\xa9\x36\x7b\x1b\xce\x76\x4c\x3f\x3e\x9b\x34\x60\x0e\xce" +
+	"\xd1\xda\x60\xcc\xf1\x2b\xe1\xdc\x37\x43\x5d\x66\x6a\x36\x8a\x4f" +
+	"\x48\x95\x6f\x63\x0f\x83\x50\xd4\xb9\x4b\xcb\x49\x72\x7c\xd6\x45" +
+	"\x66\x1e\x0b\xa2\xe2\x6e\xa1\xf2\xb0\x1e\x89\x41\xf5\xa8\x71\x4f" +
+	"\x2c\xfc\xa6\xb9\x10\xdd\x71\x4b\x37\xed\xd3\xaa\xce\xb0\x12\x6f" +
+	"\xcf\xb1\x6a\xc2\xbd\x7f\xcd\xa3\xaa\x70\xaf\xe8\xf4\x03\xe8\xdc" +
+	"\x03\x84\x50\xa3\xfd\xfd\x79\xa4\x91\x86\xa1\x3e\xf7\x7d\xe8\xe7" +
+	"\x95\xd1\x0e\x45\xe9\x28\xb3\xfc\xb2\x75\x97\x05\xae\xb5\x24\x02" +
+	"\x37\x47\xa5\x6b\x7c\xc7\x4e\xeb\x67\xa8\x7a\x53\x4b\x12\x45\xac" +
+	"\x11\x75\x8a\xc4\x34\x9f\x0a\xcc\x85\x45\xf7\x9f\x50\x98\x4c\x38" +
+	"\x27\x48\xb8\x33\xf4\xe3\xab\x7f\xe3\xd1\xda\xb5\x5d\x16\x3b\xfb" +
+	"\x52\xac\xd7\x2c\xb0\x11\x3c\x28\xf2\xf3\xeb\x9e\x2b\x66\x0c\xf3" +
+	"\x7a\x3c\x1d\x88\x0c\x41\x3a\x82\xa4\xa6\xcf\xaf\x0d\xd1\xaf\xa9" +
+	"\x56\xd8\xae\x2b\x81\x1f\x69\x2c\x4a\xfb\xef\x77\x28\xce\x84\x26" +
+	"\xbb\x89\x4d\x8a\x56\xb4\xe2\x5f\xb9\xa0\x5f\x92\xb4\xea\xaa\xad" +
+	"\x90\xa0\xe7\x66\x88\x8c\x66\xb9\xb8\x28\x2c\xcf\x47\x18\x7b\xd4" +
+	"\xc8\x4a\x7b\x68\xcb\xe1\x13\xf0\xdf\x82\x2c\xf3\xd3\x6a\xc3\x87" +
+	"\x76\x64\x18\xaa\x01\x97\xe2\x37\x8f\x65\x8c\xfe\xb2\xd7\x8d\x15" +
+	"\xee\x7e\x66\x8e\x23\x40\xc4\x3c\xd4\xe8\xae\x8f\xae\xb0\xdb\xbd" +
+	"\xfc\xd9\x04\x84\xf8\x4a\x37\x9e\xd8\x3c\x55\x1f\x9e\x7b\x4e\x96" +
+	"\xf4\x47\xdb\xad\xa5\xe7\xb7\xca\xbb\x63\x83\x7f\xb6\x1d\x41\x52" +
+	"\xfb\x2b\x31\x1f\x57\x62\xb2\x08\xf7\xc8\x60\xe8\xa8\x24\x4c\xa7" +
+	"\x54\xc7\x15\x71\xed\x3a\xdc\xf9\x9a\xfe\x3b\xf0\xf5\x7d\x10\xc5" +
+	"\x6e\xc2\x32\xb2\x7b\x6f\xe3\xbd\x5f\x73\x2d\xd3\x17\xa1\x70\x1e" +
+	"\xa2\x7e\xcc\xec\x8a\x1b\xc3\x7b\x46\xfe\x1e\x38\xd1\x04\xff\x7d" +
+	"\xf4\xfe\x2f\x00\x00\xff\xff\x82\xb7\xc1\xb2\x11\x07\x00\x00"
+
+// snakeoilCrt returns raw, uncompressed file data.
+func snakeoilCrt() []byte {
+	var empty [0]byte
+	sx := (*reflect.StringHeader)(unsafe.Pointer(&_snakeoilCrt))
+	b := empty[:]
+	bx := (*reflect.SliceHeader)(unsafe.Pointer(&b))
+	bx.Data = sx.Data
+	bx.Len = len(_snakeoilCrt)
+	bx.Cap = bx.Len
+
+	gz, err := gzip.NewReader(bytes.NewBuffer(b))
+
+	if err != nil {
+		panic("Decompression failed: " + err.Error())
+	}
+
+	var buf bytes.Buffer
+	io.Copy(&buf, gz)
+	gz.Close()
+
+	return buf.Bytes()
+}

+ 190 - 0
src/ngrok/server/tls/snakeoil.key.go

@@ -0,0 +1,190 @@
+package tls
+
+import (
+	"bytes"
+	"compress/gzip"
+	"io"
+	"reflect"
+	"unsafe"
+)
+
+var _snakeoilKey = "" +
+	"\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\x6c\x97\xb7\xb2\x84\x48" +
+	"\x94\x6d\x7d\xbe\xa2\x7d\xe2\x05\x5a\x19\xcf\x40\x6b\xad\xf1\x0a" +
+	"\x5d\x68\x4d\xc1\xd7\xcf\xed\x8e\x31\x27\xdd\xb4\x72\xe5\x8e\x73" +
+	"\xd6\xfe\x7f\xff\x1e\x4e\x94\x55\xeb\x1f\xcf\x67\xff\x71\x3c\x35" +
+	"\x62\x03\xf1\x1f\x5d\x4c\xff\xbb\x01\x4c\x55\xd5\x74\x56\xe5\x58" +
+	"\x56\xe7\xd9\x46\x64\xd1\x2f\x51\x18\x1b\x3b\x2c\x37\xdd\x44\x8d" +
+	"\xaf\xce\x4d\xfa\x91\x63\x4d\x57\xe4\xd7\x48\xde\x70\x9f\x82\xad" +
+	"\x1d\x4c\xa7\xe0\xc4\x9f\x6d\xc0\x38\x0c\x90\x3f\xd9\x2d\x4b\xbb" +
+	"\x79\x5d\x2d\x89\x7a\xd8\xae\x54\x70\x2a\xfa\xe6\x54\xd3\x6b\x4a" +
+	"\x43\x70\xf2\x25\x78\x20\x39\x81\x9c\x1c\x07\x64\x6d\xab\xf6\x15" +
+	"\xf8\xd6\x32\x4a\x7c\xbf\xcf\x7c\x0e\x9d\x07\x58\xb4\xbf\x06\x68" +
+	"\x58\xa6\x33\x3d\x0a\x38\x6e\x6e\x2f\xb7\x25\x10\x4f\xb0\xf8\x46" +
+	"\x91\x39\x53\x76\x35\xf7\x3b\x46\xf6\x74\xf2\xc2\x2d\xef\x5c\x3b" +
+	"\x13\x48\x4c\x47\x6f\x21\xd6\x39\x45\xc1\x7d\x04\x3a\xa8\x95\x39" +
+	"\xf5\x02\x2d\x7b\x9c\x3c\xd8\x4a\x17\x3f\x9d\xe5\xc1\xac\x1b\x10" +
+	"\x77\x96\xd3\x4f\x9e\x79\x61\x59\x28\x22\xc9\x64\x19\x0c\xfc\x73" +
+	"\x81\x71\x18\x35\xc3\x67\xe3\x39\xac\x54\x9d\xf2\x03\x28\xd0\x16" +
+	"\x75\xdf\x7a\xbd\x6d\xf2\x47\xe6\x29\xc2\xc7\x68\x15\x26\x1c\x35" +
+	"\x44\x46\x78\x80\xdf\x21\x86\xa9\x92\x4a\xb1\x01\x64\x70\xcf\x43" +
+	"\x4e\x21\x6b\xec\xf7\x20\x69\xa4\x0d\x37\x2a\x36\x7c\x1f\xb0\x3b" +
+	"\x0f\x76\x0a\x1b\x39\x3f\x12\x95\x14\x84\xc0\x1c\x2b\x01\x49\x77" +
+	"\xf9\x26\xb2\x0d\x7f\xee\x69\xba\xf8\xf7\x29\x71\xfa\x6a\xc9\x8e" +
+	"\xa4\x63\xdc\x19\x78\xeb\x85\x3d\x0d\xb2\xc9\x52\x23\x73\x1f\x10" +
+	"\x8d\x9e\x1d\xd9\xf8\xfc\xe5\x66\xfb\x7d\xae\xc3\x7f\x74\x7c\xce" +
+	"\xbf\x1c\x07\x3b\xc9\x7e\xe1\xf6\x97\x0b\xf5\x45\xfa\x21\x6d\x45" +
+	"\xf2\x3b\xed\xf6\x38\x6a\xfc\x9a\xbc\x24\x24\x11\x62\x04\xd4\x8f" +
+	"\x80\xba\x61\x72\x63\x27\x46\x67\x5f\x6a\x48\x94\x4f\xc6\xe8\x33" +
+	"\xdc\x44\xd7\xdd\x8a\x6f\xfa\xf2\xf2\xbc\x09\x27\x88\xd1\xc9\x77" +
+	"\x97\xd4\xc4\x63\xde\xde\xd2\xbe\x2b\xec\xb4\x23\x07\x85\x99\x6c" +
+	"\x04\x00\x25\x69\x5b\x95\xc3\x3c\x3b\x71\x29\x5e\xe5\xab\x6a\xf8" +
+	"\x69\xcd\x21\x68\x67\xd2\x07\x86\xab\x10\xfd\xee\x4c\x67\x32\xa2" +
+	"\xad\x65\x1d\x43\xca\x8d\x1a\xeb\x8b\xc8\xf3\x51\x43\xf9\x1f\x71" +
+	"\x53\x47\x00\x6c\x4d\xd2\xde\x16\x53\x6a\xbf\x13\x74\x1f\xbf\x73" +
+	"\x01\x17\xdf\xed\x66\x4b\x2f\xa7\x8c\x46\x90\x62\x76\x74\x7d\xff" +
+	"\xa9\x84\xd3\x6c\x31\x29\x84\x77\xb9\x6e\x4f\x7b\x12\xf7\xb9\x29" +
+	"\x54\x5f\x69\x00\x35\x60\xb3\xba\xc8\x7c\x81\x25\xe3\x3d\xb1\xe9" +
+	"\xdc\x19\xf9\x01\x0a\xf3\x2e\xd8\x46\x98\x7d\x70\xc3\x9a\x62\xb7" +
+	"\x5a\x6d\x82\x57\xaa\x36\x02\x71\x71\x2d\x22\xf0\x07\x1f\x7e\x11" +
+	"\xf2\xec\x2d\xb2\x00\xeb\xfe\x1b\x61\x2e\x27\xbd\x93\x36\xe0\xe6" +
+	"\x08\xb9\x09\x53\x67\xc5\xac\xb1\xd8\xd1\x21\x9e\xae\x8c\x36\x58" +
+	"\xdf\x2d\x55\x63\x2c\x96\xd2\xbb\xc5\x51\x73\x8f\x47\x8c\xad\x6c" +
+	"\x94\xb4\x7c\xdf\x05\x6c\xd9\xe3\x93\xdd\xfe\xc3\xac\xe5\x60\x77" +
+	"\xc3\x47\x66\x1a\x21\xb2\x59\x7c\xc0\x8d\xcf\xcc\xa9\xdd\x97\x23" +
+	"\x3b\x18\x2f\x52\x94\x2b\x40\x03\x86\xea\x98\x47\x31\xd2\x16\xcc" +
+	"\x0d\xdb\x35\xc9\x83\x81\x55\xed\x55\x49\x29\x82\xb2\x5e\xa4\x53" +
+	"\x5c\x71\x1f\xf9\x09\x38\x24\x1f\x61\x16\x46\xc3\x45\x75\xb0\xa1" +
+	"\xcb\x74\x0e\xa7\x10\xa3\x74\xac\x37\x51\x6b\x7e\x43\xba\xd6\x56" +
+	"\x4a\xc5\xb7\x72\xde\x8a\x00\xde\xf4\x07\xc1\x75\xd4\x19\xd2\x54" +
+	"\x4b\x75\x0a\x7b\x2f\x3d\x09\x95\xc3\x0d\x57\x7d\x0a\xc3\x39\xd4" +
+	"\x9c\xbe\x59\x1a\x10\xa1\x23\x5f\x7a\x07\x17\x9c\x5c\xa9\x5d\xa9" +
+	"\x4e\xda\x77\x90\x72\x3d\x62\x80\x7f\x2b\x6c\xd0\xb5\x40\x98\xf4" +
+	"\xdc\xe0\x98\xae\x17\x7a\x5a\xe5\x11\xb5\xc9\x3b\x03\xae\x4d\x35" +
+	"\x81\x6f\x5c\x7e\x61\xc5\xd3\x6a\x1c\x0e\x88\xef\x2c\x9f\xff\xfe" +
+	"\x14\x24\x85\x13\x3f\x3e\x25\x09\xdc\xa4\x6b\xae\x22\xa4\x59\xd5" +
+	"\x1e\xd4\xd2\xfa\x5b\xbd\x37\xe3\xee\x40\x43\xc0\x5f\x9f\xf4\xbe" +
+	"\x34\x4a\x6d\xc6\x98\x45\xfd\x1b\xc5\x63\x7e\x3f\x27\x6c\x28\x64" +
+	"\x70\xf4\xf2\xa8\x5c\xf5\x38\x91\x10\xa0\xd2\xea\x38\xa8\xde\xa3" +
+	"\xc8\x76\x18\x29\xbb\xc8\x7a\x74\x41\x7d\x04\xa6\xfc\x34\xb0\x91" +
+	"\x27\x63\xf7\xcc\x43\xfd\x9d\x68\x61\xbe\x11\x0c\x86\x64\xac\x0d" +
+	"\x92\x74\x12\xc4\xe0\x47\x92\x3d\xe2\x05\x00\xd7\x92\xbd\x20\xa6" +
+	"\xd7\xf9\xbb\xa4\xb5\x4f\x52\xdd\x63\x4f\xe2\x44\x90\xcb\x65\x99" +
+	"\xb3\x4c\x57\x0b\xff\x82\xed\xe1\xa2\xb6\x9d\xda\xa2\x6e\x25\xb4" +
+	"\xfe\x7b\x08\x12\xdd\x92\xa6\xa4\x09\xf3\x09\x80\x2a\x30\x70\x61" +
+	"\x6c\x21\x52\xa3\xa2\x23\x96\xf1\xc9\x42\x65\x7a\x99\x3a\xc2\x68" +
+	"\x18\xc6\xa5\xeb\x57\x94\xdc\x51\x32\xa4\x42\x87\x7b\xed\x56\x4e" +
+	"\x18\x5f\xb4\xcf\xba\x29\x06\x78\x2a\x4a\x49\x04\x80\x6e\xd7\x0e" +
+	"\xbb\xc1\x4b\x98\x57\x27\xba\x47\x25\x53\xb4\x8d\xd0\xb2\x42\x28" +
+	"\x22\x10\x9d\x3a\xad\xcf\xef\xca\x59\x9a\xb8\x35\xe3\x87\xc0\x67" +
+	"\x91\xb8\xea\x1a\xb2\xc8\x06\xbf\x84\x37\xa6\x20\x17\xd0\xc2\x1f" +
+	"\x16\xe2\x08\x1a\x5d\x50\x5e\x96\x16\x79\x56\x27\xbd\x96\xf4\x2b" +
+	"\xcc\xd3\x03\x9d\x2a\x21\xcb\xdc\xa7\x19\x53\x3e\x54\x9e\x7b\xb5" +
+	"\x7e\xee\x7f\xc9\x75\x45\x16\x52\x60\x93\xd7\xd2\x08\x88\x3c\xcf" +
+	"\x38\xeb\xac\x7f\xb1\x7a\xe1\xc1\x3b\x00\x8b\x79\xcd\x9b\xf3\xde" +
+	"\x02\x34\x5f\x22\xee\xb4\xca\xeb\x11\xf4\x54\xed\xf3\xc2\x17\x0e" +
+	"\x35\xb2\x76\x1b\x42\x16\x04\xe2\xe5\x79\x1b\x85\x61\x00\x7a\xa4" +
+	"\xb3\xa4\xd6\x03\x87\x95\xe3\x68\xd7\xad\x73\x24\xab\x0e\x67\x6e" +
+	"\x7f\xaf\x63\x4d\x85\xf3\xd5\x9e\x25\x67\xc2\xef\x75\x52\xb2\x8c" +
+	"\x98\x56\xa8\x68\x61\x55\x48\x07\x7d\xaa\x41\x91\x32\xd8\x0e\x84" +
+	"\x8d\xc7\x45\x3b\xbf\x18\x4d\xe8\x50\xbe\x44\x8e\x88\xb9\x9c\x28" +
+	"\xf7\x49\x5c\x68\x17\x4d\xba\x4c\x79\x7f\x3c\x70\xe9\xf3\xa3\x8c" +
+	"\x18\x86\x0b\x75\x31\x86\x2a\x1b\xf9\x64\x2e\xa0\x6e\x0f\x42\x13" +
+	"\xf8\xfe\xd2\xc0\x24\x36\x22\x8c\x13\xae\x1d\x10\x86\x34\xea\x13" +
+	"\x8c\xbb\x60\x9c\x7f\x72\x23\x55\xc1\x2d\xd1\x3f\xe4\x3e\x67\x6a" +
+	"\x74\x2f\xa7\xde\xbe\xcb\x15\x26\x50\xde\xc9\x1e\x3e\x13\x9a\x6b" +
+	"\xdf\x00\xa2\xc2\x89\x8e\x60\xcf\xd6\x4a\xbd\xc8\xaa\x11\x89\x4c" +
+	"\x0a\x27\x7f\x9f\x76\xd4\xfc\xd6\xf9\xf8\x2a\x7a\x0a\x67\xf9\x83" +
+	"\xb3\xbe\x3e\x43\xd5\x44\x42\xe9\x5a\xab\x35\xde\x3b\x36\xf8\x18" +
+	"\xa3\x1d\x03\x09\x35\x88\xf0\x6a\x35\x14\x31\xec\xde\xff\x12\xc6" +
+	"\x82\x62\x6d\xae\xef\xbe\x33\x1f\xdc\xbe\x37\x98\xfb\x34\x43\x65" +
+	"\xe7\xe1\x14\x98\xd2\xdb\xd3\x79\xb3\x54\xa3\x55\xbe\x5f\x9c\xaa" +
+	"\x64\x80\xe2\x09\x0a\x8d\x7f\xb4\xbc\x93\x49\x63\xe5\x36\x4a\x0f" +
+	"\x8b\x08\x3b\x02\xa5\x87\x90\x77\x1d\x18\x79\x3b\xcc\xf8\xca\x5f" +
+	"\x07\x36\xb1\x6c\xc3\x5b\x1a\x61\x6b\xe3\xaa\x8f\xd9\x34\x77\xf2" +
+	"\x39\x7a\xe0\x56\x34\xbb\x3c\x9c\x90\xcf\xd6\x6b\xca\x87\x4b\xb7" +
+	"\x55\x1c\x66\x26\x79\x9a\x43\x01\xc4\xa6\x5a\x81\xd6\x55\xe9\xf1" +
+	"\xcc\xc0\xea\x09\xbf\x94\xfc\x77\x9b\x73\x99\xd5\x76\xe2\x6d\x0a" +
+	"\xda\x6a\x1b\x20\x46\x2b\x3b\x4d\xd5\xef\xcb\xf8\xb0\x96\x6b\xda" +
+	"\xaf\x2c\xfc\x81\x33\x55\xe2\x72\x4d\xfd\x2f\x70\x1d\x81\xf2\xe8" +
+	"\x58\x17\x12\x98\x78\xe6\x29\xd1\x74\x7e\xd7\xda\xdf\x0a\xca\xb1" +
+	"\xa7\x7d\x2e\xfa\x0b\x2c\x89\xa2\x64\x19\xe3\xea\xe2\xdf\x83\x28" +
+	"\x32\xb4\x41\x51\xd6\x5f\xba\x99\xb0\x3b\xd6\xcf\x96\x50\x92\x05" +
+	"\x53\xe6\x47\xff\x96\xcd\x9b\x1c\x8e\x9a\x9f\x74\x5d\xe2\xe1\x9b" +
+	"\x0c\x10\xf7\x87\xa4\x00\xba\x98\x95\xe1\xb4\xd8\x47\xa2\x0c\xe6" +
+	"\xdc\x85\xd3\x19\x4e\xaa\xee\x24\x94\x9d\x70\xf9\x43\x3d\x52\xca" +
+	"\x66\xa5\x5d\x81\x9a\xff\x00\x73\x1c\x1f\xf0\x4c\x98\x58\x9d\xcd" +
+	"\xdc\xd9\x92\xe6\x33\x20\x94\x33\xdb\xfb\x13\x2b\x1a\x7f\x34\xe6" +
+	"\x11\xfd\x35\x3e\x58\xc1\x38\xae\x20\x5e\x7f\x91\x27\x95\xd9\xa8" +
+	"\x8a\x14\x5a\xa0\x54\x54\xad\xf3\x6d\xd9\xa7\xd6\x6b\xc4\xe8\x30" +
+	"\x12\xb0\x2b\x80\x48\x0d\xd4\x1e\x5e\x6b\x8c\x8c\xf0\xf7\xe0\x8a" +
+	"\x8b\x42\xbe\x9b\xbb\x52\x5c\x3e\xdd\x79\x8b\xab\x76\xb2\x99\xe5" +
+	"\xbc\xca\xf9\xdc\x1d\xab\x34\x74\xd9\xce\xac\x82\xd5\xcc\xf5\x4f" +
+	"\x0f\x59\x4e\xfd\x86\x98\x0e\x2c\xa5\xb8\xa4\x8b\x25\xf8\x9e\x9d" +
+	"\x3d\xa1\x51\xe6\xf4\xc0\x1c\xe7\x49\x68\x5e\x75\x17\x67\xdb\xb8" +
+	"\x4d\x35\xa0\x7d\x8f\x6e\xf6\x6b\xd2\xdc\x02\x9e\x0b\xa5\x9f\x29" +
+	"\x37\x4e\x8f\xab\xf1\x55\x38\x03\x15\x4c\x3c\xd0\x5e\xd3\xc8\x7e" +
+	"\x81\x8d\xbc\x2d\xdc\x6b\x1c\xf7\x57\x7c\xdf\x9f\x84\x16\x90\xb4" +
+	"\x4e\x93\x7c\xff\xa4\x0b\xcb\x30\x6e\xeb\xa3\x91\xa8\xf2\x66\xae" +
+	"\x32\x68\x80\xd9\xa4\x7f\xcd\x81\x07\xb0\x3b\x99\x9d\x5c\xd2\xf6" +
+	"\x9f\x94\x7d\x64\x8d\x7a\x1d\x14\x2d\x39\x41\x6e\x2c\x7c\x8e\xcc" +
+	"\x89\xbf\xf7\x05\x63\xf5\xd0\xa2\x4f\xba\xa4\xc7\x2e\x1c\x84\xf2" +
+	"\xcb\x64\x0a\x11\xf0\x64\x22\xbd\x5c\x00\x10\x2f\x2b\xb1\xf3\x9f" +
+	"\xa5\x49\x7c\x37\x24\x63\x01\x9b\x75\x04\x33\xe4\x97\x4b\xd3\x27" +
+	"\x81\x3f\x56\xb0\x40\x93\x8b\x3f\x86\x57\x4c\x94\x5a\x8f\x7b\x9b" +
+	"\x0a\xad\x0c\x5e\xf3\x54\xf7\xba\x64\x1e\x33\x80\xd0\x08\xd3\x28" +
+	"\x9f\x8f\xfc\x8b\xcd\x43\x0a\xa5\x1a\x8c\x6d\x33\x25\x53\x9d\xe1" +
+	"\x6e\x2a\x4e\x65\x5f\x57\xb4\x38\x31\xd6\x91\xb3\x10\x3e\x6c\x29" +
+	"\x25\x5a\xe1\xcb\x3c\x9e\x84\xbc\x8e\x08\x72\x5d\x20\x0c\x1b\x6a" +
+	"\x9c\xaf\xbf\x81\xcf\x9d\xa7\xb2\xd0\xd3\x22\x0a\x6e\x1b\x84\x76" +
+	"\x68\xc9\xb0\x6d\x81\x38\x9f\xa7\x19\x56\xea\x79\x7c\xb0\x59\x54" +
+	"\x29\xd6\xa7\x90\x71\xda\x47\xd6\x5b\xcc\x1c\x03\x39\x81\xf0\x1b" +
+	"\x06\xfb\x11\x58\x2b\x93\xfa\x4d\xaf\x82\xa9\xd4\xdc\x15\xcf\xca" +
+	"\xb2\x53\xcc\xa7\xc7\x21\x12\x5f\xae\xc2\xeb\x28\x7d\x71\x45\x50" +
+	"\x42\x57\x75\xe6\x86\x6a\xb0\xfb\xb2\x09\xde\x53\x12\xc3\x80\xdc" +
+	"\xd1\x15\x46\x67\x85\x76\xc5\x2a\x8c\x8f\xce\x2c\xc0\x0e\x13\x7f" +
+	"\x8c\x16\xf2\x71\x7c\x01\x3d\x71\xe8\x42\xe6\x90\xb5\x21\x79\x57" +
+	"\x03\x1d\xad\x71\x28\x9e\x3a\x7a\x84\x77\x6b\xc1\x86\xd5\x1c\xe0" +
+	"\x4d\x57\xf2\x64\x93\xe2\xb5\xee\x1a\x0a\x25\xa8\x23\x67\x5e\xa3" +
+	"\xd1\x4f\x84\xbe\x70\x74\x8b\x7c\xd3\x88\x1c\xab\x35\x1f\x54\xcf" +
+	"\x91\xf9\xb2\x0c\xd3\xa5\xa3\x73\x44\x0e\x91\xe6\xec\xfe\x64\x04" +
+	"\xa0\x0d\xa2\xe5\x05\x77\xe9\x6c\xb2\x33\x25\x84\x77\x60\x76\x47" +
+	"\x0e\xb0\x30\x91\xbb\x2c\xa3\x17\x59\x94\x17\xc3\x71\x75\x34\x75" +
+	"\x88\xa7\x00\xab\x96\x9f\x1a\xac\x72\x8e\x24\x82\x77\x27\xf4\x88" +
+	"\x18\x40\xa8\xee\x9b\x9b\xa8\x96\x4a\xbd\xc7\x78\x1a\xcf\xb3\x74" +
+	"\x01\x82\xa8\x7d\xff\xb2\x20\xd2\xfe\x46\x79\xd8\x2b\x32\x55\x2c" +
+	"\x03\xe1\x1a\xf9\x6b\x6b\x6c\x2c\x53\xf4\x9f\x29\x7f\xad\x35\x13" +
+	"\x1f\x1e\x06\xbc\x3d\xd5\x9d\x4f\x49\x56\x70\x35\xa5\x87\x73\xa5" +
+	"\xc3\xc4\xa7\x1b\x45\xa5\xb8\x6e\x91\x63\x48\xd8\x07\x66\xbf\xab" +
+	"\x5c\x39\x38\x08\x96\xa1\xf9\x4e\x06\x8a\x5c\x39\x7a\x8f\x7f\x66" +
+	"\xab\x18\x7f\x86\x62\xde\x1f\xf2\xa6\x6a\x35\x49\x2d\xd6\x3e\xf9" +
+	"\x1e\x96\xcd\x2a\x7d\x7d\x25\x0b\xa8\x2c\x7d\x8e\x30\x6c\xbf\xdf" +
+	"\x20\xca\x95\xec\xfc\xbc\x9a\x47\x6a\x8f\x47\x3d\x35\x56\x4e\x5d" +
+	"\xef\xd4\x5e\xa4\x54\xc0\x6a\xec\xfa\xdf\xbe\xc9\x9f\xf8\xf3\xe7" +
+	"\xd5\x24\x52\x5b\x59\x5c\x5b\xb8\xd4\x18\xe6\x18\x0a\x2f\x6f\x59" +
+	"\xc2\xcb\xec\x52\x02\x33\xda\x88\xb8\x1f\x71\x06\x85\x73\xa2\x84" +
+	"\x9b\xf6\xf7\xff\x0f\xfc\x57\x39\x44\x4b\xf8\xbf\xab\xc8\xff\x04" +
+	"\x00\x00\xff\xff\x14\x22\x96\x1d\xab\x0c\x00\x00"
+
+// snakeoilKey returns raw, uncompressed file data.
+func snakeoilKey() []byte {
+	var empty [0]byte
+	sx := (*reflect.StringHeader)(unsafe.Pointer(&_snakeoilKey))
+	b := empty[:]
+	bx := (*reflect.SliceHeader)(unsafe.Pointer(&b))
+	bx.Data = sx.Data
+	bx.Len = len(_snakeoilKey)
+	bx.Cap = bx.Len
+
+	gz, err := gzip.NewReader(bytes.NewBuffer(b))
+
+	if err != nil {
+		panic("Decompression failed: " + err.Error())
+	}
+
+	var buf bytes.Buffer
+	io.Copy(&buf, gz)
+	gz.Close()
+
+	return buf.Bytes()
+}