From 67151c071b364ceede20d14e48f8a05331d62d05 Mon Sep 17 00:00:00 2001 From: guox191 Date: Mon, 25 Mar 2019 22:47:49 +0800 Subject: [PATCH 1/3] support select CA file extension --- lib/webInterface.js | 26 +++++---------- test/spec_lib/webInterface.js | 44 +++++++++++++++++++++++++ web/src/component/download-root-ca.jsx | 42 +++++++++++++++++------ web/src/component/download-root-ca.less | 5 +++ 4 files changed, 89 insertions(+), 28 deletions(-) create mode 100644 test/spec_lib/webInterface.js diff --git a/lib/webInterface.js b/lib/webInterface.js index 9620663..4285728 100644 --- a/lib/webInterface.js +++ b/lib/webInterface.js @@ -1,7 +1,5 @@ 'use strict'; -const DEFAULT_WEB_PORT = 8002; // port for web interface - const express = require('express'), url = require('url'), bodyParser = require('body-parser'), @@ -16,9 +14,13 @@ const express = require('express'), ip = require('ip'), compress = require('compression'); +const DEFAULT_WEB_PORT = 8002; // port for web interface + const packageJson = require('../package.json'); const MAX_CONTENT_SIZE = 1024 * 2000; // 2000kb + +const certFileTypes = ['crt', 'cer', 'pem', 'der']; /** * * @@ -204,8 +206,9 @@ class webInterface extends events.EventEmitter { res.setHeader('Access-Control-Allow-Origin', '*'); const _crtFilePath = certMgr.getRootCAFilePath(); if (_crtFilePath) { + const fileType = certFileTypes.indexOf(req.query.type) !== -1 ? req.query.type : 'crt'; res.setHeader('Content-Type', 'application/x-x509-ca-cert'); - res.setHeader('Content-Disposition', 'attachment; filename="rootCA.crt"'); + res.setHeader('Content-Disposition', `attachment; filename="rootCA.${fileType}"`); res.end(fs.readFileSync(_crtFilePath, { encoding: null })); } else { res.setHeader('Content-Type', 'text/html'); @@ -213,25 +216,12 @@ class webInterface extends events.EventEmitter { } }); - //make qr code - app.get('/qr', (req, res) => { - res.setHeader('Access-Control-Allow-Origin', '*'); - res.setHeader('Content-Type', 'text/html'); - - const qr = qrCode.qrcode(4, 'M'); - const targetUrl = req.protocol + '://' + req.get('host'); - qr.addData(targetUrl); - qr.make(); - const qrImageTag = qr.createImgTag(4); - const resDom = ' __img
click or scan qr code to start client
'.replace(/__url/, targetUrl).replace(/__img/, qrImageTag); - res.end(resDom); - }); - app.get('/api/getQrCode', (req, res) => { res.setHeader('Access-Control-Allow-Origin', '*'); + const fileType = certFileTypes.indexOf(req.query.type) !== -1 ? req.query.type : 'crt'; const qr = qrCode.qrcode(4, 'M'); - const targetUrl = req.protocol + '://' + req.get('host') + '/fetchCrtFile'; + const targetUrl = req.protocol + '://' + req.get('host') + '/fetchCrtFile?type=' + fileType; const isRootCAFileExists = certMgr.isRootCAFileExists(); qr.addData(targetUrl); diff --git a/test/spec_lib/webInterface.js b/test/spec_lib/webInterface.js new file mode 100644 index 0000000..3eac176 --- /dev/null +++ b/test/spec_lib/webInterface.js @@ -0,0 +1,44 @@ +const WebInterface = require('../../lib/webInterface.js'); +const Recorder = require('../../lib/recorder'); +const { directGet } = require('../util/HttpUtil.js'); + +describe('WebInterface server', () => { + let webServer = null; + let webHost = 'http://127.0.0.1:8002'; + + beforeAll(() => { + const recorder = new Recorder(); + webServer = new WebInterface({ + webPort: 8002, + }, recorder); + }); + + afterAll(() => { + webServer.close(); + }); + + it('should support change CA extensions in /getQrCode', done => { + const certFileTypes = ['crt', 'cer', 'pem', 'der']; + const tasks = certFileTypes.map((type) => { + return directGet(`${webHost}/api/getQrCode`, { type }) + .then(res => { + const body = JSON.parse(res.body); + expect(body.qrImgDom).toMatch(' - + + Or click the button to download. @@ -146,7 +169,6 @@ class DownloadRootCA extends React.Component { return ( {this.props.globalStatus.isRootCAFileExists ? this.getDownloadDiv() : this.getGenerateRootCADiv()} - ); } diff --git a/web/src/component/download-root-ca.less b/web/src/component/download-root-ca.less index 8c9d1de..550227d 100644 --- a/web/src/component/download-root-ca.less +++ b/web/src/component/download-root-ca.less @@ -55,4 +55,9 @@ margin-top: 18px; display: block; } +} + +.fileSelect { + width: 60px; + margin-left: 8px; } \ No newline at end of file From 15d7ed48bfa57912c6b081c6f942349e8ce2ee82 Mon Sep 17 00:00:00 2001 From: guox191 Date: Mon, 25 Mar 2019 23:53:47 +0800 Subject: [PATCH 2/3] docs tip --- docs-src/cn/README.md | 26 ++++++++++++++------------ docs-src/cn/src_doc.md | 2 ++ docs-src/en/README.md | 28 +++++++++++++++------------- docs-src/en/src_doc.md | 4 +++- 4 files changed, 34 insertions(+), 26 deletions(-) diff --git a/docs-src/cn/README.md b/docs-src/cn/README.md index 2841a81..c36b1e9 100644 --- a/docs-src/cn/README.md +++ b/docs-src/cn/README.md @@ -536,8 +536,8 @@ module.exports = { anyproxy --rule rule_sample/sample_use_local_response.js ``` ```js -/* - sample: +/* + sample: intercept all requests toward httpbin.org, use a local response test: curl http://httpbin.org/user-agent --proxy http://127.0.0.1:8001 @@ -566,8 +566,8 @@ module.exports = { anyproxy --rule rule_sample/sample_modify_request_header.js ``` ```js -/* - sample: +/* + sample: modify the user-agent in requests toward httpbin.org test: curl http://httpbin.org/user-agent --proxy http://127.0.0.1:8001 @@ -655,8 +655,8 @@ module.exports = { anyproxy --rule rule_sample/sample_modify_request_protocol.js ``` ```js -/* - sample: +/* + sample: redirect all http requests of httpbin.org to https test: curl 'http://httpbin.org/get?show_env=1' --proxy http://127.0.0.1:8001 @@ -685,8 +685,8 @@ module.exports = { anyproxy --rule rule_sample/sample_modify_response_statuscode.js ``` ```js -/* - sample: +/* + sample: modify all status code of http://httpbin.org/ to 404 test: curl -I 'http://httpbin.org/user-agent' --proxy http://127.0.0.1:8001 @@ -714,8 +714,8 @@ module.exports = { anyproxy --rule rule_sample/sample_modify_response_header.js ``` ```js -/* - sample: +/* + sample: modify response header of http://httpbin.org/user-agent test: curl -I 'http://httpbin.org/user-agent' --proxy http://127.0.0.1:8001 @@ -743,8 +743,8 @@ module.exports = { anyproxy --rule rule_sample/sample_modify_response_data.js ``` ```js -/* - sample: +/* + sample: modify response data of http://httpbin.org/user-agent test: curl 'http://httpbin.org/user-agent' --proxy http://127.0.0.1:8001 @@ -827,6 +827,8 @@ module.exports = { * 设置 -> 安全性与位置信息 -> 加密与凭据 -> 从存储设备安装。找到你下载的证书文件,进行安装 * 设置 -> 安全 -> 从SD卡安装证书。找到你下载的证书文件,进行安装 +不同安卓系统支持安装的证书文件类型也不尽相同,大多数系统支持安装拓展名为 .crt 的证书文件,少部分仅支持 .cer 文件(已知如 OPPO R15),AnyProxy 提供了多种类型的证书文件可在下载安装时选择。 + ### 配置iOS/Android系统代理 * 代理服务器都在wifi设置中配置 diff --git a/docs-src/cn/src_doc.md b/docs-src/cn/src_doc.md index ccc2e75..1241f11 100644 --- a/docs-src/cn/src_doc.md +++ b/docs-src/cn/src_doc.md @@ -628,6 +628,8 @@ module.exports = { * 设置 -> 安全性与位置信息 -> 加密与凭据 -> 从存储设备安装。找到你下载的证书文件,进行安装 * 设置 -> 安全 -> 从SD卡安装证书。找到你下载的证书文件,进行安装 +不同安卓系统支持安装的证书文件类型也不尽相同,大多数系统支持安装拓展名为 .crt 的证书文件,少部分仅支持 .cer 文件(已知如 OPPO R15),AnyProxy 提供了多种类型的证书文件可在下载安装时选择。 + ### 配置iOS/Android系统代理 * 代理服务器都在wifi设置中配置 diff --git a/docs-src/en/README.md b/docs-src/en/README.md index adcdba7..3e798e4 100644 --- a/docs-src/en/README.md +++ b/docs-src/en/README.md @@ -528,8 +528,8 @@ module.exports = { anyproxy --rule rule_sample/sample_use_local_response.js ``` ```js -/* - sample: +/* + sample: intercept all requests toward httpbin.org, use a local response test: curl http://httpbin.org/user-agent --proxy http://127.0.0.1:8001 @@ -558,8 +558,8 @@ module.exports = { anyproxy --rule rule_sample/sample_modify_request_header.js ``` ```js -/* - sample: +/* + sample: modify the user-agent in requests toward httpbin.org test: curl http://httpbin.org/user-agent --proxy http://127.0.0.1:8001 @@ -647,8 +647,8 @@ module.exports = { anyproxy --rule rule_sample/sample_modify_request_protocol.js ``` ```js -/* - sample: +/* + sample: redirect all http requests of httpbin.org to https test: curl 'http://httpbin.org/get?show_env=1' --proxy http://127.0.0.1:8001 @@ -677,8 +677,8 @@ module.exports = { anyproxy --rule rule_sample/sample_modify_response_statuscode.js ``` ```js -/* - sample: +/* + sample: modify all status code of http://httpbin.org/ to 404 test: curl -I 'http://httpbin.org/user-agent' --proxy http://127.0.0.1:8001 @@ -706,8 +706,8 @@ module.exports = { anyproxy --rule rule_sample/sample_modify_response_header.js ``` ```js -/* - sample: +/* + sample: modify response header of http://httpbin.org/user-agent test: curl -I 'http://httpbin.org/user-agent' --proxy http://127.0.0.1:8001 @@ -735,8 +735,8 @@ module.exports = { anyproxy --rule rule_sample/sample_modify_response_data.js ``` ```js -/* - sample: +/* + sample: modify response data of http://httpbin.org/user-agent test: curl 'http://httpbin.org/user-agent' --proxy http://127.0.0.1:8001 @@ -809,6 +809,8 @@ install : * Besides installing root CA, you have to "turn on" the certificate for web manually in *settings - general - about - Certificate Trust Settings*. Otherwire, safari will not trust the root CA generated by AnyProxy. + + ### trust root CA in Android First of all, you need to download the root CA by clicking *Root CA* in web ui, and then scan the QR code. Installing CA in Android could be different based on the system, we list some common steps as below, but you can find the right way in you system with similar menu path. @@ -818,7 +820,7 @@ Installing CA in Android could be different based on the system, we list some co * Settings -> Security & Location > Encryption & credentials -> Install from storage, and find your CA file to install * Settings -> Security -> Install from SD card, and find you CA file to install - +As we konw, there are several file extensions of CA file which may not recognised by all kinds of Android OS. The .crt file is the most popular, and a few systems only support .cer file such as OPPO R15. In AnyProxy, you can choose what type of file you need before installing the root CA to your devices. ### config iOS/Android proxy server diff --git a/docs-src/en/src_doc.md b/docs-src/en/src_doc.md index 5597927..9f5f5e3 100644 --- a/docs-src/en/src_doc.md +++ b/docs-src/en/src_doc.md @@ -610,6 +610,8 @@ install : * Besides installing root CA, you have to "turn on" the certificate for web manually in *settings - general - about - Certificate Trust Settings*. Otherwire, safari will not trust the root CA generated by AnyProxy. + + ### trust root CA in Android First of all, you need to download the root CA by clicking *Root CA* in web ui, and then scan the QR code. Installing CA in Android could be different based on the system, we list some common steps as below, but you can find the right way in you system with similar menu path. @@ -619,7 +621,7 @@ Installing CA in Android could be different based on the system, we list some co * Settings -> Security & Location > Encryption & credentials -> Install from storage, and find your CA file to install * Settings -> Security -> Install from SD card, and find you CA file to install - +As we konw, there are several file extensions of CA file which may not recognised by all kinds of Android OS. The .crt file is the most popular, and a few systems only support .cer file such as OPPO R15. In AnyProxy, you can choose what type of file you need before installing the root CA to your devices. ### config iOS/Android proxy server From 7f026640794d16a6ea8391676679f76b69195af9 Mon Sep 17 00:00:00 2001 From: guox191 Date: Tue, 26 Mar 2019 14:11:22 +0800 Subject: [PATCH 3/3] add CA download page --- docs-src/en/README.md | 2 +- docs-src/en/src_doc.md | 2 +- lib/webInterface.js | 11 ++- resource/cert_download.pug | 91 +++++++++++++++++++++++++ test/spec_lib/webInterface.js | 24 ++----- web/src/component/download-root-ca.jsx | 42 +++--------- web/src/component/download-root-ca.less | 5 -- 7 files changed, 116 insertions(+), 61 deletions(-) create mode 100644 resource/cert_download.pug diff --git a/docs-src/en/README.md b/docs-src/en/README.md index 3e798e4..4ae4407 100644 --- a/docs-src/en/README.md +++ b/docs-src/en/README.md @@ -820,7 +820,7 @@ Installing CA in Android could be different based on the system, we list some co * Settings -> Security & Location > Encryption & credentials -> Install from storage, and find your CA file to install * Settings -> Security -> Install from SD card, and find you CA file to install -As we konw, there are several file extensions of CA file which may not recognised by all kinds of Android OS. The .crt file is the most popular, and a few systems only support .cer file such as OPPO R15. In AnyProxy, you can choose what type of file you need before installing the root CA to your devices. +As we known, there are several file extensions of CA file which may not be recognised by all kinds of Android. The .crt file is the most popular, and a few systems only support .cer file such as OPPO R15. In AnyProxy, you can choose the type of file you need before installing the root CA to your devices. ### config iOS/Android proxy server diff --git a/docs-src/en/src_doc.md b/docs-src/en/src_doc.md index 9f5f5e3..ab017f0 100644 --- a/docs-src/en/src_doc.md +++ b/docs-src/en/src_doc.md @@ -621,7 +621,7 @@ Installing CA in Android could be different based on the system, we list some co * Settings -> Security & Location > Encryption & credentials -> Install from storage, and find your CA file to install * Settings -> Security -> Install from SD card, and find you CA file to install -As we konw, there are several file extensions of CA file which may not recognised by all kinds of Android OS. The .crt file is the most popular, and a few systems only support .cer file such as OPPO R15. In AnyProxy, you can choose what type of file you need before installing the root CA to your devices. +As we known, there are several file extensions of CA file which may not be recognised by all kinds of Android. The .crt file is the most popular, and a few systems only support .cer file such as OPPO R15. In AnyProxy, you can choose the type of file you need before installing the root CA to your devices. ### config iOS/Android proxy server diff --git a/lib/webInterface.js b/lib/webInterface.js index 4285728..57212e0 100644 --- a/lib/webInterface.js +++ b/lib/webInterface.js @@ -12,7 +12,8 @@ const express = require('express'), wsServer = require('./wsServer'), juicer = require('juicer'), ip = require('ip'), - compress = require('compression'); + compress = require('compression'), + pug = require('pug'); const DEFAULT_WEB_PORT = 8002; // port for web interface @@ -202,6 +203,11 @@ class webInterface extends events.EventEmitter { } }); + app.get('/downloadCrt', (req, res) => { + const pageFn = pug.compileFile(path.join(__dirname, '../resource/cert_download.pug')); + res.end(pageFn({ ua: req.get('user-agent') })); + }); + app.get('/fetchCrtFile', (req, res) => { res.setHeader('Access-Control-Allow-Origin', '*'); const _crtFilePath = certMgr.getRootCAFilePath(); @@ -219,9 +225,8 @@ class webInterface extends events.EventEmitter { app.get('/api/getQrCode', (req, res) => { res.setHeader('Access-Control-Allow-Origin', '*'); - const fileType = certFileTypes.indexOf(req.query.type) !== -1 ? req.query.type : 'crt'; const qr = qrCode.qrcode(4, 'M'); - const targetUrl = req.protocol + '://' + req.get('host') + '/fetchCrtFile?type=' + fileType; + const targetUrl = req.protocol + '://' + req.get('host') + '/downloadCrt'; const isRootCAFileExists = certMgr.isRootCAFileExists(); qr.addData(targetUrl); diff --git a/resource/cert_download.pug b/resource/cert_download.pug new file mode 100644 index 0000000..5c5762b --- /dev/null +++ b/resource/cert_download.pug @@ -0,0 +1,91 @@ +doctype html +html(lang="en") + head + title Download rootCA + meta(name='viewport', content='initial-scale=1, maximum-scale=0.5, minimum-scale=1, user-scalable=no') + style. + body { + color: #666; + line-height: 1.5; + font-size: 16px; + font-family: -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Helvetica,PingFang SC,Hiragino Sans GB,Microsoft YaHei,SimSun,sans-serif; + } + + body * { + box-sizing: border-box; + } + + .logo { + font-size: 36px; + margin-bottom: 40px; + text-align: center; + } + + .any { + font-weight: 500; + } + + .proxy { + font-weight: 100; + } + + .title { + font-weight: bold; + margin: 20px 0 6px; + } + + .button { + text-align: center; + padding: 4px 15px 5px 15px; + font-size: 14px; + font-weight: 500; + border-radius: 4px; + height: 32px; + margin-bottom: 10px; + display: block; + text-decoration: none; + border-color: #108ee9; + color: rgba(0, 0, 0, .65); + background-color: #fff; + border-style: solid; + border-width: 1px; + border-style: solid; + border-color: #d9d9d9; + } + + .primary { + color: #fff; + background-color: #108ee9; + border-color: #108ee9; + } + + .more { + text-align: center; + font-size: 14px; + } + + .content { + word-break: break-all; + font-size: 14px; + line-height: 1.2; + margin-bottom: 10px; + } + body + .logo + span.any Any + span.proxy Proxy + .title Download: + .content Select a CA file to download, the .crt file is commonly used. + a(href="/fetchCrtFile?type=crt").button.primary rootCA.crt + a(href="/fetchCrtFile?type=cer").button rootCA.cer + .more More + .buttons(style='display: none') + a(href="/fetchCrtFile?type=pem").button rootCA.pem + a(href="/fetchCrtFile?type=der").button rootCA.der + .title User-Agent: + .content #{ua} + script(type='text/javascript'). + window.document.querySelector('.more').addEventListener('click', function (e) { + e.target.style.display = 'none'; + window.document.querySelector('.buttons').style.display = 'block'; + }); \ No newline at end of file diff --git a/test/spec_lib/webInterface.js b/test/spec_lib/webInterface.js index 3eac176..1975943 100644 --- a/test/spec_lib/webInterface.js +++ b/test/spec_lib/webInterface.js @@ -17,26 +17,12 @@ describe('WebInterface server', () => { webServer.close(); }); - it('should support change CA extensions in /getQrCode', done => { - const certFileTypes = ['crt', 'cer', 'pem', 'der']; - const tasks = certFileTypes.map((type) => { - return directGet(`${webHost}/api/getQrCode`, { type }) - .then(res => { - const body = JSON.parse(res.body); - expect(body.qrImgDom).toMatch(' { this.setState({ loadingCAQr: false, @@ -60,33 +57,12 @@ class DownloadRootCA extends React.Component { this.props.dispatch(hideRootCA()); } - onFileTypeChange (value) { - this.setState({ - fileType: value - }, () => { - this.fetchData(); - }); - } - getQrCodeContent () { const imgDomContent = { __html: this.state.CAQrCodeImageDom }; const content = (
-
Scan to download rootCA.{this.state.fileType} to your Phone
-
You can change the CA's file extension: - -
+ Scan to download rootCA to your Phone
); @@ -95,6 +71,7 @@ class DownloadRootCA extends React.Component { } getGenerateRootCADiv () { + const doToggleRemoteIntercept = () => { postJSON('/api/generateRootCA') .then((result) => { @@ -150,8 +127,8 @@ class DownloadRootCA extends React.Component {
- - + + Or click the button to download.
@@ -169,6 +146,7 @@ class DownloadRootCA extends React.Component { return ( {this.props.globalStatus.isRootCAFileExists ? this.getDownloadDiv() : this.getGenerateRootCADiv()} + ); } diff --git a/web/src/component/download-root-ca.less b/web/src/component/download-root-ca.less index 550227d..8c9d1de 100644 --- a/web/src/component/download-root-ca.less +++ b/web/src/component/download-root-ca.less @@ -55,9 +55,4 @@ margin-top: 18px; display: block; } -} - -.fileSelect { - width: 60px; - margin-left: 8px; } \ No newline at end of file