asd123a20 4 年 前
コミット
cf627a2697
65 ファイル変更1588 行追加0 行削除
  1. 29 0
      .autod.conf.js
  2. 1 0
      .eslintignore
  3. 3 0
      .eslintrc
  4. 14 0
      .gitignore
  5. 12 0
      .travis.yml
  6. 53 0
      app/controller/admin.js
  7. 121 0
      app/controller/card.js
  8. 323 0
      app/controller/cert.js
  9. 24 0
      app/controller/home.js
  10. 198 0
      app/controller/vpn.js
  11. 1 0
      app/public/css/app.d9cb9654.css
  12. 1 0
      app/public/css/chunk-1b296e02.e67b2ace.css
  13. 1 0
      app/public/css/chunk-26ac09aa.915aed1d.css
  14. 1 0
      app/public/css/chunk-3813fef6.967ae014.css
  15. 1 0
      app/public/css/chunk-50149b5a.d6cc05f7.css
  16. 1 0
      app/public/css/chunk-7030f5aa.352f0d2b.css
  17. 1 0
      app/public/css/chunk-79924bbd.a4fe5c3f.css
  18. 1 0
      app/public/css/chunk-8a0a9ef6.490c3d98.css
  19. 1 0
      app/public/css/chunk-e7be95dc.d73f7837.css
  20. 1 0
      app/public/css/chunk-ecf1724e.5274e45a.css
  21. 1 0
      app/public/css/chunk-f43862f0.4e08efc6.css
  22. 1 0
      app/public/css/chunk-vendors.84bb20f7.css
  23. BIN
      app/public/favicon.ico
  24. BIN
      app/public/fonts/element-icons.535877f5.woff
  25. BIN
      app/public/fonts/element-icons.732389de.ttf
  26. BIN
      app/public/img/bg2.4f6e6589.jpg
  27. BIN
      app/public/img/home.a18367d8.png
  28. 1 0
      app/public/img/logo1.191c3d70.svg
  29. 1 0
      app/public/index.html
  30. 1 0
      app/public/js/app.6bc835f1.js
  31. 1 0
      app/public/js/chunk-1b296e02.b5f99aad.js
  32. 1 0
      app/public/js/chunk-26ac09aa.99413aad.js
  33. 1 0
      app/public/js/chunk-3813fef6.364de217.js
  34. 1 0
      app/public/js/chunk-50149b5a.0160a1ce.js
  35. 1 0
      app/public/js/chunk-7030f5aa.d693ddfa.js
  36. 1 0
      app/public/js/chunk-79924bbd.e5128c73.js
  37. 1 0
      app/public/js/chunk-8a0a9ef6.d08de0f3.js
  38. 1 0
      app/public/js/chunk-e7be95dc.e6130621.js
  39. 1 0
      app/public/js/chunk-ecf1724e.7b2a590a.js
  40. 1 0
      app/public/js/chunk-f43862f0.ea0a1136.js
  41. 33 0
      app/public/js/chunk-vendors.2addda4d.js
  42. 48 0
      app/router.js
  43. 210 0
      app/service/files.js
  44. 10 0
      app/view/dhcp.nj
  45. 13 0
      app/view/ipsecalog.nj
  46. 23 0
      app/view/ipsecavpn.nj
  47. 26 0
      app/view/ipsecavpnservice.nj
  48. 13 0
      app/view/lan.nj
  49. 28 0
      app/view/sslvpn.nj
  50. 37 0
      app/view/sslvpnservice.nj
  51. 14 0
      app/view/wan.nj
  52. 14 0
      appveyor.yml
  53. 75 0
      config/config.default.js
  54. 21 0
      config/plugin.js
  55. 5 0
      jsconfig.json
  56. 22 0
      node_cache/_logs/2020-12-12T06_00_03_533Z-debug.log
  57. 15 0
      node_cache/_logs/2020-12-14T06_59_18_276Z-debug.log
  58. 15 0
      node_cache/_logs/2020-12-16T03_47_08_002Z-debug.log
  59. 15 0
      node_cache/_logs/2020-12-17T06_03_46_278Z-debug.log
  60. 15 0
      node_cache/_logs/2020-12-22T07_51_58_271Z-debug.log
  61. 34 0
      node_cache/_logs/2020-12-23T02_17_23_381Z-debug.log
  62. 15 0
      node_cache/_logs/2020-12-24T02_13_14_176Z-debug.log
  63. 15 0
      node_cache/_logs/2020-12-28T05_33_37_064Z-debug.log
  64. 49 0
      package.json
  65. 20 0
      test/app/controller/home.test.js

+ 29 - 0
.autod.conf.js

@@ -0,0 +1,29 @@
+'use strict';
+
+module.exports = {
+  write: true,
+  prefix: '^',
+  plugin: 'autod-egg',
+  test: [
+    'test',
+    'benchmark',
+  ],
+  dep: [
+    'egg',
+    'egg-scripts',
+  ],
+  devdep: [
+    'egg-ci',
+    'egg-bin',
+    'egg-mock',
+    'autod',
+    'autod-egg',
+    'eslint',
+    'eslint-config-egg',
+  ],
+  exclude: [
+    './test/fixtures',
+    './dist',
+  ],
+};
+

+ 1 - 0
.eslintignore

@@ -0,0 +1 @@
+coverage

+ 3 - 0
.eslintrc

@@ -0,0 +1,3 @@
+{
+  "extends": "eslint-config-egg"
+}

+ 14 - 0
.gitignore

@@ -0,0 +1,14 @@
+logs/
+npm-debug.log
+yarn-error.log
+node_modules/
+package-lock.json
+yarn.lock
+coverage/
+.idea/
+run/
+.DS_Store
+*.sw*
+*.un~
+typings/
+.nyc_output/

+ 12 - 0
.travis.yml

@@ -0,0 +1,12 @@
+
+language: node_js
+node_js:
+  - '10'
+before_install:
+  - npm i npminstall -g
+install:
+  - npminstall
+script:
+  - npm run ci
+after_script:
+  - npminstall codecov && codecov

+ 53 - 0
app/controller/admin.js

@@ -0,0 +1,53 @@
+/* eslint-disable array-callback-return */
+'use strict';
+const Controller = require('egg').Controller;
+class AdminController extends Controller {
+  async login() {
+    const { ctx, app } = this;
+    const { userName, password } = ctx.request.body;
+    const person = require(app.config.filePath.configJson);
+    const data = person.admin.filter(p => p.userName === userName);
+    let msg;
+    if (data.length <= 0) {
+      msg = { errcode: -1, errmsg: '用户不存在' };
+    } else {
+      if (data[0].password === password) {
+        const token = app.jwt.sign({ userName, name: data[0].name }, app.config.jwt.secret, {
+          expiresIn: 60 * 60 * 60,
+        });
+        msg = { errcode: 0, errmsg: '', token, userName, name: data[0].name };
+      } else {
+        msg = { errcode: -1, errmsg: '密码错误' };
+      }
+    }
+    ctx.body = msg;
+  }
+  async editPwa() {
+    const { ctx } = this;
+    const { userName, password, newpassword } = ctx.request.body;
+    const person = require(this.app.config.filePath.configJson);
+    const jsaonfilePath = this.app.config.filePath.configJson;
+    const data = person.admin.filter(p => p.userName === userName);
+    let msg;
+    if (data.length <= 0) {
+      msg = { errcode: -1, errmsg: '用户不存在' };
+    } else {
+      if (data[0].password === password) {
+        person.admin.map(p => {
+          if (p.userName === userName) {
+            p.password = newpassword;
+          }
+        });
+        const jsonstr = JSON.stringify(person);
+        await this.service.files.write({ filePath: jsaonfilePath, str: jsonstr });
+        msg = { errcode: 0, errmsg: '' };
+      } else {
+        msg = { errcode: -1, errmsg: '密码错误' };
+      }
+    }
+    ctx.body = msg;
+  }
+}
+
+
+module.exports = AdminController;

+ 121 - 0
app/controller/card.js

@@ -0,0 +1,121 @@
+'use strict';
+const Controller = require('egg').Controller;
+class CertController extends Controller {
+  // wan添加
+  async wanadd() {
+    const login = await this.service.files.login();
+    if (login.errcode !== 0) {
+      this.ctx.body = login;
+      return false;
+    }
+    try {
+      const { ctx } = this;
+      const { address, netmask, gateway, type } = ctx.request.body;
+      const form = { type, address: address || '192.168.0.10', netmask: netmask || '255.255.255.0', gateway: gateway || '192.168.0.1' };
+      const filePath = this.app.config.filePath.configJson;
+      const person = require(this.app.config.filePath.configJson);
+      person.wan = form;
+      const jsonstr = JSON.stringify(person);
+      const paths = this.app.config.filePath.wan;
+      // 写入自己管理的文件
+      await this.service.files.write({ filePath, str: jsonstr });
+      const wanstr = await ctx.renderView('wan.nj', form);
+      console.log(wanstr);
+      // 写入配置文件
+      await this.service.files.write({ filePath: paths, str: wanstr });
+      ctx.body = { errcode: 0, errmsg: '' };
+    } catch (error) {
+      // this.ctx.body = { errcode: -2, errmsg: error };
+      throw error;
+    }
+  }
+  // lan添加
+  async lanadd() {
+    const login = await this.service.files.login();
+    if (login.errcode !== 0) {
+      this.ctx.body = login;
+      return false;
+    }
+    const { ctx } = this;
+    try {
+      const form = { ...ctx.request.body };
+      const filePath = this.app.config.filePath.configJson;
+      const person = require(this.app.config.filePath.configJson);
+      person.lan = { address: form.address || '192.168.3.1', type: form.type };
+      person.dhcp = { start: form.start || '120', end: form.end || '200', address: form.address || '192.168.3.1' };
+      const jsonstr = JSON.stringify(person);
+      await this.service.files.write({ filePath, str: jsonstr });
+      const items = [];
+      if (!form.address) {
+        form.address = '192.168.3.1';
+      }
+      for (let index = 0; index < form.address.length; index++) {
+        if (form.address[index] === '.') {
+          items.push(index);
+        }
+      }
+      form.addressTow = form.address.slice(0, items[2]);
+      const lanstr = await ctx.renderView('lan.nj', form);
+      const paths = this.app.config.filePath.lan;
+      await this.service.files.write({ filePath: paths, str: lanstr });
+      if (form.type === 0) {
+        form.start = form.start || '120';
+        form.end = form.end || '200';
+        const dhcpstr = await ctx.renderView('dhcp.nj', form);
+        // 写入dhcp
+        const dhcppath = this.app.config.filePath.dhcpd;
+        const dhcpres = await this.service.files.write({ filePath: dhcppath, str: dhcpstr });
+        // 启动dhcp
+        if (dhcpres.errcode === 0) {
+          await this.service.files.dhcp({ type: 'enable' });
+        }
+      } else {
+      // 停止dhcp服务
+        await this.service.files.dhcp({ type: 'disable' });
+      }
+      ctx.body = { errcode: 0, errmsg: '' };
+    } catch (error) {
+      // console.log(error);
+      // this.ctx.body = { errcode: -2, errmsg: error };
+      throw error;
+    }
+  }
+  // wan查询
+  async wanquery() {
+    try {
+      const { ctx } = this;
+      const person = require(this.app.config.filePath.configJson);
+      const data = person.wan;
+      ctx.body = { errcode: 0, errmsg: '', data };
+    } catch (error) {
+      // this.ctx.body = { errcode: -2, errmsg: error };
+      throw error;
+    }
+  }
+  // lan查询
+  async lanquery() {
+    try {
+      const { ctx } = this;
+      const person = require(`${this.app.config.filePath.configJson}`);
+      const data = person.lan;
+      ctx.body = { errcode: 0, errmsg: '', data };
+    } catch (error) {
+      // this.ctx.body = { errcode: -2, errmsg: error };
+      throw error;
+    }
+  }
+  // dhcp查询
+  async dhcpquery() {
+    try {
+      const { ctx } = this;
+      const person = require(this.app.config.filePath.configJson);
+      const data = person.dhcp;
+      ctx.body = { errcode: 0, errmsg: '', data };
+    } catch (error) {
+      // this.ctx.body = { errcode: -2, errmsg: error };
+      throw error;
+    }
+  }
+}
+
+module.exports = CertController;

+ 323 - 0
app/controller/cert.js

@@ -0,0 +1,323 @@
+/* eslint-disable array-callback-return */
+'use strict';
+const UUID = require('uuid');
+const fs = require('fs');
+const path = require('path');
+const sendToWormhole = require('stream-wormhole');
+const Controller = require('egg').Controller;
+class CertController extends Controller {
+  // ca上传证书
+  async cacertupload() {
+    const login = await this.service.files.login();
+    if (login.errcode !== 0) {
+      this.ctx.body = login;
+      return false;
+    }
+    try {
+      const { ctx } = this;
+      const uuid = UUID.v1();
+      const stream = await ctx.getFileStream();
+      const uri = this.app.config.filePath.ca;
+      const filePath = `${this.app.config.filePath.ca}${uuid}.cer`;
+      const jsaonfilePath = this.app.config.filePath.configJson;
+      const person = require(this.app.config.filePath.configJson);
+      // 存储证书
+      const res = await this.service.files.upload({ uuid, stream, uri });
+      if (res.errcode === 0) {
+        // 解析证书
+        const dns = await this.service.files.read({ filePath });
+        let dn;
+        if (dns.errcode === 0) {
+          dns.data.trim().split('\n').forEach(function(v) {
+            if (v.includes('Subject:')) {
+              dn = v.replace('Subject:', '');
+            }
+          });
+        }
+        if (dns.errcode === 0) {
+          const form = { uuid, dn };
+          person.ca.push(form);
+          const jsonstr = JSON.stringify(person);
+          // 存储数据
+          await this.service.files.write({ filePath: jsaonfilePath, str: jsonstr });
+        } else {
+          throw dns;
+        }
+      } else {
+        sendToWormhole(stream);
+      }
+      ctx.body = res;
+    } catch (error) {
+      // this.ctx.body = { errcode: -2, errmsg: error };
+      throw error;
+    }
+  }
+  // ca证书下载
+  async cacertdownload() {
+    try {
+      const uuid = this.ctx.query.uuid;
+      const filePath = `${this.app.config.filePath.ca}${uuid}.cer`;
+      const target = path.join(filePath);
+      fs.readFile(target, function(err) {
+        if (err) {
+          throw err;
+        }
+      });
+      const res = await this.service.files.download({ filePath });
+      this.ctx.body = res;
+    } catch (error) {
+      // this.ctx.body = { errcode: -2, errmsg: error };
+      throw error;
+    }
+  }
+  // ca证书查询
+  async cacertquery() {
+    try {
+      const { ctx } = this;
+      const person = require(this.app.config.filePath.configJson);
+      const data = person.ca;
+      const total = data.length;
+      ctx.body = { errcode: 0, errmsg: '', data, total };
+    } catch (error) {
+      // this.ctx.body = { errcode: -2, errmsg: error };
+      throw error;
+    }
+  }
+  // ca证书删除
+  async cacertdelete() {
+    const login = await this.service.files.login();
+    if (login.errcode !== 0) {
+      this.ctx.body = login;
+      return false;
+    }
+    try {
+      const uuid = this.ctx.query.uuid;
+      const jsaonfilePath = this.app.config.filePath.configJson;
+      const person = require(this.app.config.filePath.configJson);
+      const data = person.ca.filter(p => p.uuid !== uuid);
+      person.ca = data;
+      const jsonstr = JSON.stringify(person);
+      await this.service.files.write({ filePath: jsaonfilePath, str: jsonstr });
+      const files = [
+        `${this.app.config.filePath.ca}${uuid}.cer`,
+      ];
+      files.forEach(e => {
+        const cafile = path.join(e);
+        fs.unlink(cafile, function(err) {
+          if (err) {
+            throw err;
+          }
+        });
+      });
+      this.ctx.body = { errcode: 0, errmsg: '' };
+    } catch (error) {
+      // this.ctx.body = { errcode: -2, errmsg: error };
+      throw error;
+    }
+  }
+  // 设备证书-创建申请书
+  async devcertadd() {
+    const login = await this.service.files.login();
+    if (login.errcode !== 0) {
+      this.ctx.body = login;
+      return false;
+    }
+    try {
+      const { ctx } = this;
+      const uuid = UUID.v1();
+      const { dn, pwatype, name } = ctx.request.body;
+      const state = 0;
+      const reskey = await this.service.files.applykey({ ...ctx.request.body, uuid });
+      if (reskey.errcode === 0) {
+        const resreq = await this.service.files.applyreq({ ...ctx.request.body, uuid });
+        if (resreq.errcode === 0) {
+          const form = { state, dn, pwatype, name, uuid };
+          const filePath = this.app.config.filePath.configJson;
+          const person = require(this.app.config.filePath.configJson);
+          person.cert.push(form);
+          const jsonstr = JSON.stringify(person);
+          await this.service.files.write({ filePath, str: jsonstr });
+        }
+      }
+      this.ctx.body = { errcode: 0, errmsg: '' };
+    } catch (error) {
+      // console.log(error);
+      // this.ctx.body = { errcode: -2, errmsg: error };
+      throw error;
+    }
+  }
+  // 设备证书查询
+  async devcacertquery() {
+    try {
+      const { ctx } = this;
+      const person = require(this.app.config.filePath.configJson);
+      const data = person.cert;
+      const total = data.length || 0;
+      ctx.body = { errcode: 0, errmsg: '', data, total };
+    } catch (error) {
+      // this.ctx.body = { errcode: -2, errmsg: error };
+      throw error;
+    }
+  }
+  // 删除设备证书
+  async devcacertdelete() {
+    const login = await this.service.files.login();
+    if (login.errcode !== 0) {
+      this.ctx.body = login;
+      return false;
+    }
+    try {
+      const uuid = this.ctx.query.uuid;
+      const person = require(this.app.config.filePath.configJson);
+      const cert = person.cert.filter(p => p.uuid === uuid);
+      const files = [];
+      files.push(`${this.app.config.filePath.key}${uuid}.key`);
+      if (cert[0].state === 1) {
+        files.push(`${this.app.config.filePath.cert}${uuid}.cer`);
+      }
+      files.forEach(e => {
+        const cafile = path.join(e);
+        fs.unlink(cafile, function(err) {
+          if (err) {
+            throw err;
+          }
+        });
+      });
+      const jsaonfilePath = this.app.config.filePath.configJson;
+      const data = person.cert.filter(p => p.uuid !== uuid);
+      person.cert = data;
+      const jsonstr = JSON.stringify(person);
+      await this.service.files.write({ filePath: jsaonfilePath, str: jsonstr });
+      this.ctx.body = { errcode: 0, errmsg: '' };
+    } catch (error) {
+      // this.ctx.body = { errcode: -2, errmsg: error };
+      throw error;
+    }
+  }
+  // 下载申请书
+  async reqdownload() {
+    try {
+      const uuid = this.ctx.query.uuid;
+      const filePath = `${this.app.config.filePath.req}/${uuid}.pem`;
+      const target = path.join(filePath);
+      fs.readFile(target, function(err) {
+        if (err) {
+          throw err;
+        }
+      });
+      const res = await this.service.files.download({ filePath });
+      this.ctx.body = res;
+    } catch (error) {
+      // this.ctx.body = { errcode: -2, errmsg: error };
+      throw error;
+    }
+  }
+  // 设备证书下载
+  async devcertdownload() {
+    try {
+      const uuid = this.ctx.query.uuid;
+      const filePath = `${this.app.config.filePath.cert}${uuid}.cer`;
+      const target = path.join(filePath);
+      fs.readFile(target, function(err) {
+        if (err) {
+          throw err;
+        }
+      });
+      const res = await this.service.files.download({ filePath });
+      this.ctx.body = res;
+    } catch (error) {
+      // this.ctx.body = { errcode: -2, errmsg: error };
+      throw error;
+    }
+  }
+  // 设备签名证书上传
+  async devcertupload() {
+    const login = await this.service.files.login();
+    if (login.errcode !== 0) {
+      this.ctx.body = login;
+      return false;
+    }
+    const stream = await this.ctx.getFileStream();
+    try {
+      const uuid = stream.fields.uuid;
+      const person = require(this.app.config.filePath.configJson);
+      const jsaonfilePath = this.app.config.filePath.configJson;
+      const uri = this.app.config.filePath.cert;
+      await this.service.files.upload({ uuid, stream, uri });
+      const res = await this.service.files.upload({ uuid, stream, uri });
+      if (res.errcode === 0) {
+        person.cert.map(p => {
+          if (p.uuid === uuid) {
+            p.state = 1;
+          }
+        });
+        const jsonstr = JSON.stringify(person);
+        await this.service.files.write({ filePath: jsaonfilePath, str: jsonstr });
+      }
+      this.ctx.body = res;
+    } catch (error) {
+      sendToWormhole(stream);
+      // this.ctx.body = { errcode: -2, errmsg: error };
+      throw error;
+    }
+  }
+  // p12上传
+  async devcertuploadtow() {
+    const login = await this.service.files.login();
+    if (login.errcode !== 0) {
+      this.ctx.body = login;
+      return false;
+    }
+    const { ctx } = this;
+    const stream = await ctx.getFileStream();
+    try {
+      const uuid = UUID.v1();
+      const password = stream.fields.password;
+      const name = stream.fields.name;
+      if (!password) {
+        throw { errcode: -1, errmsg: '密码不存在' };
+      }
+      const fileName = `${uuid}.p12`;
+      const target = `${this.app.config.filePath.p12}${fileName}`;
+      const jsaonfilePath = this.app.config.filePath.configJson;
+      const person = require(this.app.config.filePath.configJson);
+      const res = await this.service.files.filewrite({ filePath: target, stream });
+      if (res.errcode === 0) {
+        const keys = await this.service.files.keys({ password, target });
+        if (keys.errcode === 0) {
+          const p8 = await this.service.files.write({ filePath: `${this.app.config.filePath.key}${uuid}.p8`, str: keys.data });
+          if (p8.errcode === 0) {
+            await this.service.files.transform({ files: `${uuid}.p8`, target: `${uuid}.key` });
+          }
+        }
+        const certs = await this.service.files.certs({ password, target });
+        if (certs.errcode === 0) {
+          let dn,
+            pwatype;
+          this.service.files.write({ filePath: `${this.app.config.filePath.cert}${uuid}.cer`, str: certs.data });
+          const dns = await this.service.files.read({ filePath: `${this.app.config.filePath.cert}${uuid}.cer` });
+          if (dns.errcode === 0) {
+            dns.data.trim().split('\n').forEach(function(v) {
+              if (v.includes('Subject:')) {
+                dn = v.replace('Subject:', '');
+              }
+              if (v.includes('ASN1 OID:')) {
+                pwatype = v.replace('ASN1 OID:', '');
+              }
+            });
+          }
+          person.cert.push({ uuid, pwatype, dn, name, state: 1 });
+        }
+      }
+      const jsonstr = JSON.stringify(person);
+      await this.service.files.write({ filePath: jsaonfilePath, str: jsonstr });
+      ctx.body = { errcode: 0, errmsg: '' };
+    } catch (error) {
+      sendToWormhole(stream);
+      // ctx.body = { errcode: -2, errmsg: error };
+      throw error;
+    }
+  }
+}
+
+module.exports = CertController;

+ 24 - 0
app/controller/home.js

@@ -0,0 +1,24 @@
+/* eslint-disable array-callback-return */
+'use strict';
+// const UUID = require('uuid');
+const fs = require('fs');
+const path = require('path');
+const Controller = require('egg').Controller;
+class HomeController extends Controller {
+  async home() {
+    const { ctx } = this;
+    ctx.response.type = 'html';
+    ctx.body = fs.readFileSync(path.resolve(__dirname, '../public/index.html'));
+  }
+  async reboot() {
+    try {
+      await this.service.files.reboot();
+      this.ctx.body = { errcode: 0, errmsg: '' };
+    } catch (error) {
+      // this.ctx.body = { errcode: -1, errmsg: error };
+      throw error;
+    }
+  }
+}
+
+module.exports = HomeController;

+ 198 - 0
app/controller/vpn.js

@@ -0,0 +1,198 @@
+/* eslint-disable array-callback-return */
+'use strict';
+const Controller = require('egg').Controller;
+const path = require('path');
+const fs = require('fs');
+class VpnController extends Controller {
+  async sslvpnadd() {
+    const login = await this.service.files.login();
+    if (login.errcode !== 0) {
+      this.ctx.body = login;
+      return false;
+    }
+    try {
+      const { ctx } = this;
+      const form = ctx.request.body;
+      const jsaonfilePath = this.app.config.filePath.configJson;
+      const person = require(this.app.config.filePath.configJson);
+      person.sslvpn = form;
+      const jsonstr = JSON.stringify(person);
+      // 存储数据
+      await this.service.files.write({ filePath: jsaonfilePath, str: jsonstr });
+      form.capath = `${this.app.config.filePath.ca}${form.ca}.cer`;
+      form.certpath = `${this.app.config.filePath.cert}${form.cert}.cer`;
+      form.keys = `${this.app.config.filePath.key}${form.cert}.key`;
+      const filePath = this.app.config.filePath.sslvpn;
+      const sslvpnStr = await ctx.renderView('sslvpn.nj', form);
+      if (sslvpnStr) {
+        const res = await this.service.files.write({ filePath, str: sslvpnStr });
+        if (res.errcode === 0) {
+          // 重启
+          await this.service.files.openvpn({ type: 'restart' });
+        }
+      }
+      this.ctx.body = { errcode: 0, errmsg: '' };
+    } catch (error) {
+      throw error;
+    }
+  }
+  async sslvpnserviceadd() {
+    const login = await this.service.files.login();
+    if (login.errcode !== 0) {
+      this.ctx.body = login;
+      return false;
+    }
+    try {
+      const { ctx } = this;
+      const form = ctx.request.body;
+      const jsaonfilePath = this.app.config.filePath.configJson;
+      const person = require(this.app.config.filePath.configJson);
+      person.sslvpnservice = form;
+      const jsonstr = JSON.stringify(person);
+      // 存储数据
+      await this.service.files.write({ filePath: jsaonfilePath, str: jsonstr });
+      form.capath = `${this.app.config.filePath.ca}${form.ca}.cer`;
+      form.certpath = `${this.app.config.filePath.cert}${form.cert}.cer`;
+      form.keys = `${this.app.config.filePath.key}${form.cert}.key`;
+      const filePath = this.app.config.filePath.sslvpn;
+      const sslvpnserviceStr = await ctx.renderView('sslvpnservice.nj', form);
+      if (sslvpnserviceStr) {
+        const res = await this.service.files.write({ filePath, str: sslvpnserviceStr });
+        if (res.errcode === 0) {
+          // 重启
+          await this.service.files.openvpn({ type: 'restart' });
+        }
+      }
+      this.ctx.body = { errcode: 0, errmsg: '' };
+    } catch (error) {
+      throw error;
+    }
+  }
+  // ssl查询
+  async sslquery() {
+    try {
+      const { ctx } = this;
+      const person = require(this.app.config.filePath.configJson);
+      const data = person.sslvpn;
+      ctx.body = { errcode: 0, errmsg: '', data };
+    } catch (error) {
+      throw error;
+    }
+  }
+  async sslserivcequery() {
+    try {
+      const { ctx } = this;
+      const person = require(this.app.config.filePath.configJson);
+      const data = person.sslvpnservice;
+      ctx.body = { errcode: 0, errmsg: '', data };
+    } catch (error) {
+      throw error;
+    }
+  }
+  // ipsecvpn查询
+  async ipsecquery() {
+    try {
+      const { ctx } = this;
+      const person = require(this.app.config.filePath.configJson);
+      const data = person.ipsecvpn;
+      ctx.body = { errcode: 0, errmsg: '', data };
+    } catch (error) {
+      throw error;
+    }
+  }
+  async ipsecadd() {
+    const login = await this.service.files.login();
+    if (login.errcode !== 0) {
+      this.ctx.body = login;
+      return false;
+    }
+    try {
+      const { ctx } = this;
+      const form = ctx.request.body;
+      const jsaonfilePath = this.app.config.filePath.configJson;
+      const person = require(this.app.config.filePath.configJson);
+      person.ipsecvpn = form;
+      const jsonstr = JSON.stringify(person);
+      // 存储数据
+      await this.service.files.write({ filePath: jsaonfilePath, str: jsonstr });
+      const filePath = this.app.config.filePath.ipsec;
+      const logfilePath = this.app.config.filePath.ipseclog;
+      form.start = form.start || '0';
+      form.end = form.end || '24';
+      form.certpath = `${this.app.config.filePath.cert}${form.cert}.cer`;
+      const ipsecavpnStr = await ctx.renderView('ipsecavpn.nj', form);
+      const ipsecalog = await ctx.renderView('ipsecalog.nj', form);
+      if (ipsecavpnStr) {
+        const res = await this.service.files.write({ filePath, str: ipsecavpnStr });
+        if (res.errcode === 0) {
+          if (ipsecalog) {
+            const logres = await this.service.files.write({ filePath: logfilePath, str: ipsecalog });
+            if (logres.errcode === 0) {
+              // 重启
+              await this.service.files.ipsecas({ type: 'restart ' });
+            }
+          }
+        }
+      }
+      this.ctx.body = { errcode: 0, errmsg: '' };
+    } catch (error) {
+      throw error;
+    }
+  }
+  // ipsecvpn查询
+  async ipsecservicequery() {
+    try {
+      const { ctx } = this;
+      const person = require(this.app.config.filePath.configJson);
+      const data = person.ipsecservice;
+      ctx.body = { errcode: 0, errmsg: '', data };
+    } catch (error) {
+      throw error;
+    }
+  }
+  async ipsecserviceadd() {
+    const login = await this.service.files.login();
+    if (login.errcode !== 0) {
+      this.ctx.body = login;
+      return false;
+    }
+    try {
+      const { ctx } = this;
+      const form = ctx.request.body;
+      const jsaonfilePath = this.app.config.filePath.configJson;
+      const person = require(this.app.config.filePath.configJson);
+      person.ipsecservice = form;
+      const jsonstr = JSON.stringify(person);
+      // 存储数据
+      await this.service.files.write({ filePath: jsaonfilePath, str: jsonstr });
+      const filePath = this.app.config.filePath.ipsecservice;
+      const logfilePath = this.app.config.filePath.ipseclog;
+      form.certpath = `${form.cert}.cer`;
+      const ipsecavpnStr = await ctx.renderView('ipsecavpnservice.nj', form);
+      const ipsecalog = await ctx.renderView('ipsecalog.nj', form);
+      if (ipsecavpnStr) {
+        const res = await this.service.files.write({ filePath, str: ipsecavpnStr });
+        if (res.errcode === 0) {
+          if (ipsecalog) {
+            const logres = await this.service.files.write({ filePath: logfilePath, str: ipsecalog });
+            if (logres.errcode === 0) {
+              // 重启
+              await this.service.files.ipsecas({ type: 'restart ' });
+            }
+          }
+        }
+      }
+      this.ctx.body = { errcode: 0, errmsg: '' };
+    } catch (error) {
+      throw error;
+    }
+  }
+  async download() {
+    const filePath = path.join('/var/log/charon.log');
+    this.ctx.attachment('charon.log');
+    this.ctx.set('Content-Type', 'application/octet-stream');
+    this.ctx.body = fs.createReadStream(filePath);
+  }
+}
+
+module.exports = VpnController;

ファイルの差分が大きいため隠しています
+ 1 - 0
app/public/css/app.d9cb9654.css


ファイルの差分が大きいため隠しています
+ 1 - 0
app/public/css/chunk-1b296e02.e67b2ace.css


ファイルの差分が大きいため隠しています
+ 1 - 0
app/public/css/chunk-26ac09aa.915aed1d.css


+ 1 - 0
app/public/css/chunk-3813fef6.967ae014.css

@@ -0,0 +1 @@
+.gafBox[data-v-4a482c51]{height:90vh;overflow:hidden}.el-card[data-v-4a482c51]{height:100%}.el-card[data-v-4a482c51] .el-card__body{height:90%;overflow:auto}.el-card[data-v-4a482c51] .el-card__body .el-form{width:90%;margin:0 auto}.el-select[data-v-4a482c51]{width:100%}.el-switch[data-v-4a482c51]{width:90%;margin:0 auto;display:block;text-indent:1.7em;margin-bottom:20px}

+ 1 - 0
app/public/css/chunk-50149b5a.d6cc05f7.css

@@ -0,0 +1 @@
+.demo-form-inline[data-v-72f3a11a]{margin-left:1%;margin-top:10px}.prepend.el-select[data-v-72f3a11a]{width:100px}.table[data-v-16cb7e1c]{width:98%;margin:0 auto;max-height:60vh;overflow-y:auto}.pagination[data-v-f44c3072]{margin-left:1%;margin-top:20px}.gafBox[data-v-0877f48f]{height:100%}.upload-demo[data-v-0877f48f]{float:right;margin:0 5px}.el-card[data-v-0877f48f]{height:100%}.el-card .el-main .grid[data-v-0877f48f],.el-card .el-main[data-v-0877f48f]{width:100%}

+ 1 - 0
app/public/css/chunk-7030f5aa.352f0d2b.css

@@ -0,0 +1 @@
+.el-card[data-v-32acac71],.gafBox[data-v-32acac71]{height:100%}.el-card .el-main[data-v-32acac71]{display:flex}.el-card .el-main .el-card[data-v-32acac71]{width:45%;margin:0 3%;height:75vh}

+ 1 - 0
app/public/css/chunk-79924bbd.a4fe5c3f.css

@@ -0,0 +1 @@
+.gafBox[data-v-6d8012e4]{height:90vh;overflow:hidden}.el-card[data-v-6d8012e4]{height:100%}.el-card[data-v-6d8012e4] .el-card__body{height:90%;overflow:auto}.el-card[data-v-6d8012e4] .el-card__body .el-form{width:90%;margin:0 auto}.el-select[data-v-6d8012e4]{width:100%}

+ 1 - 0
app/public/css/chunk-8a0a9ef6.490c3d98.css

@@ -0,0 +1 @@
+.gafBox[data-v-f9b0e5e4]{height:100%}.upload-demo[data-v-f9b0e5e4]{float:right;margin:0 5px}.el-card[data-v-f9b0e5e4]{height:100%}.el-card .el-main .grid[data-v-f9b0e5e4],.el-card .el-main[data-v-f9b0e5e4]{width:100%}

+ 1 - 0
app/public/css/chunk-e7be95dc.d73f7837.css

@@ -0,0 +1 @@
+.gafBox[data-v-33b946f0]{height:90vh;overflow:hidden}.el-card[data-v-33b946f0]{height:100%}.el-card[data-v-33b946f0] .el-card__body{height:90%;overflow:auto}.el-card[data-v-33b946f0] .el-card__body .el-form{width:90%;margin:0 auto}.el-select[data-v-33b946f0]{width:100%}.el-switch[data-v-33b946f0]{width:90%;margin:0 auto;display:block;text-indent:1.7em;margin-bottom:20px}

+ 1 - 0
app/public/css/chunk-ecf1724e.5274e45a.css

@@ -0,0 +1 @@
+.gafBox[data-v-079fbb40]{height:90vh;overflow:hidden}.el-card[data-v-079fbb40]{height:100%}.el-card[data-v-079fbb40] .el-card__body{height:90%;overflow:auto}.el-card[data-v-079fbb40] .el-card__body .el-form{width:90%;margin:0 auto}.el-select[data-v-079fbb40]{width:100%}

+ 1 - 0
app/public/css/chunk-f43862f0.4e08efc6.css

@@ -0,0 +1 @@
+.wrapper[data-v-71b651fc]{height:100%;width:100%;position:relative;background-position:50%;background-repeat:o-repeat;background-size:cover;background-image:url(../img/home.a18367d8.png)}.titleWrapper[data-v-71b651fc]{text-align:center;top:40%;width:100%;position:absolute;color:#1d87b4}.title[data-v-71b651fc]{font-size:32px;letter-spacing:1.94px;line-height:2em;text-align:center}

ファイルの差分が大きいため隠しています
+ 1 - 0
app/public/css/chunk-vendors.84bb20f7.css


BIN
app/public/favicon.ico


BIN
app/public/fonts/element-icons.535877f5.woff


BIN
app/public/fonts/element-icons.732389de.ttf


BIN
app/public/img/bg2.4f6e6589.jpg


BIN
app/public/img/home.a18367d8.png


ファイルの差分が大きいため隠しています
+ 1 - 0
app/public/img/logo1.191c3d70.svg


ファイルの差分が大きいため隠しています
+ 1 - 0
app/public/index.html


ファイルの差分が大きいため隠しています
+ 1 - 0
app/public/js/app.6bc835f1.js


ファイルの差分が大きいため隠しています
+ 1 - 0
app/public/js/chunk-1b296e02.b5f99aad.js


ファイルの差分が大きいため隠しています
+ 1 - 0
app/public/js/chunk-26ac09aa.99413aad.js


ファイルの差分が大きいため隠しています
+ 1 - 0
app/public/js/chunk-3813fef6.364de217.js


ファイルの差分が大きいため隠しています
+ 1 - 0
app/public/js/chunk-50149b5a.0160a1ce.js


ファイルの差分が大きいため隠しています
+ 1 - 0
app/public/js/chunk-7030f5aa.d693ddfa.js


ファイルの差分が大きいため隠しています
+ 1 - 0
app/public/js/chunk-79924bbd.e5128c73.js


ファイルの差分が大きいため隠しています
+ 1 - 0
app/public/js/chunk-8a0a9ef6.d08de0f3.js


ファイルの差分が大きいため隠しています
+ 1 - 0
app/public/js/chunk-e7be95dc.e6130621.js


ファイルの差分が大きいため隠しています
+ 1 - 0
app/public/js/chunk-ecf1724e.7b2a590a.js


ファイルの差分が大きいため隠しています
+ 1 - 0
app/public/js/chunk-f43862f0.ea0a1136.js


ファイルの差分が大きいため隠しています
+ 33 - 0
app/public/js/chunk-vendors.2addda4d.js


+ 48 - 0
app/router.js

@@ -0,0 +1,48 @@
+'use strict';
+
+/**
+ * @param {Egg.Application} app - egg application
+ */
+module.exports = app => {
+  const { router, controller, jwt } = app;
+  router.get('/', controller.home.home);
+  router.get('/public/:frame', controller.home.home);
+  router.get('/public/:frame/:type', controller.home.home);
+  router.get('/public/:frame/:type/:path', controller.home.home);
+  // 网络
+  router.post('/api/wanadd', jwt, controller.card.wanadd);
+  router.get('/api/wanquery', jwt, controller.card.wanquery);
+  router.post('/api/lanadd', jwt, controller.card.lanadd);
+  router.get('/api/lanquery', jwt, controller.card.lanquery);
+  router.get('/api/dhcpquery', jwt, controller.card.dhcpquery);
+  // ca证书
+  router.post('/api/cacertupload', jwt, controller.cert.cacertupload);
+  router.get('/api/cacertdownload', controller.cert.cacertdownload);
+  router.get('/api/cacertquery', jwt, controller.cert.cacertquery);
+  router.get('/api/cacertdelete', jwt, controller.cert.cacertdelete);
+  // 设备证书
+  router.post('/api/devcertadd', jwt, controller.cert.devcertadd);
+  router.get('/api/devcacertquery', jwt, controller.cert.devcacertquery);
+  router.get('/api/devcacertdelete', jwt, controller.cert.devcacertdelete);
+  router.get('/api/reqdownload', controller.cert.reqdownload);
+  router.get('/api/devcertdownload', controller.cert.devcertdownload);
+  router.post('/api/devcertupload', jwt, controller.cert.devcertupload);
+  router.post('/api/devcertuploadtow', jwt, controller.cert.devcertuploadtow);
+  // sslvpn
+  router.post('/api/sslvpnadd', jwt, controller.vpn.sslvpnadd);
+  router.post('/api/sslvpnserviceadd', jwt, controller.vpn.sslvpnserviceadd);
+  router.get('/api/sslquery', jwt, controller.vpn.sslquery);
+  router.get('/api/sslserivcequery', jwt, controller.vpn.sslserivcequery);
+  // ipseccpn
+  router.get('/api/ipsecquery', jwt, controller.vpn.ipsecquery);
+  router.post('/api/ipsecadd', jwt, controller.vpn.ipsecadd);
+  router.get('/api/ipsecservicequery', jwt, controller.vpn.ipsecservicequery);
+  router.post('/api/ipsecserviceadd', jwt, controller.vpn.ipsecserviceadd);
+  // login
+  router.post('/api/login', controller.admin.login);
+  router.post('/api/editPwa', controller.admin.editPwa);
+  // reboot
+  router.get('/api/reboot', controller.home.reboot);
+  // download
+  router.get('/api/download', controller.vpn.download);
+};

+ 210 - 0
app/service/files.js

@@ -0,0 +1,210 @@
+/* eslint-disable prefer-promise-reject-errors */
+// eslint-disable-next-line strict
+const Service = require('egg').Service;
+const fs = require('fs');
+const path = require('path');
+const exec = require('child_process').exec;
+class FileService extends Service {
+  // 上传证书
+  async upload({ uuid, stream, uri }) {
+    return new Promise((resolve, reject) => {
+      const name = `${uuid}.cer`;
+      const target = path.join(`${uri}${name}`);
+      const remoteFileStream = fs.createWriteStream(target);
+      stream.pipe(remoteFileStream);
+      let errFlag;
+      remoteFileStream.on('error', err => {
+        errFlag = true;
+        remoteFileStream.destroy();
+        reject(err);
+      });
+
+      remoteFileStream.on('finish', async () => {
+        if (errFlag) return;
+        resolve({ errcode: 0, errmsg: '' });
+      });
+    });
+  }
+  // 证书下载
+  async download({ filePath }) {
+    const target = path.join(filePath);
+    this.ctx.attachment(target);
+    this.ctx.set('Content-Type', 'application/octet-stream');
+    const msg = fs.createReadStream(target);
+    return msg;
+  }
+  // 解析ca证书
+  async read({ filePath }) {
+    return new Promise((resolve, reject) => {
+      exec(`openssl x509 -in ${filePath} -noout -text -certopt no_header,no_version,no_extensions,no_sigdump,no_serial`, function(error, stdout) {
+        if (error) {
+          reject(error);
+        }
+        resolve({ errcode: 0, errmsg: '', data: stdout });
+      });
+    });
+  }
+  // 创建key
+  async applykey({ pwatype, uuid }) {
+    return new Promise((resolve, reject) => {
+      const keyname = `${this.app.config.filePath.key}${uuid}.key`;
+      // 创建密钥对
+      exec(`pki --gen --type ${pwatype} ${pwatype === 'rsa' ? '--size 2048' : ''} --outform pem`, function(error, stdout) {
+        if (error) {
+          reject(error);
+        }
+        fs.writeFile(keyname, stdout, {}, function(err) {
+          if (err) {
+            reject(err);
+          }
+          resolve({ errmsg: '', errcode: 0 });
+        });
+      });
+    });
+  }
+  async applyreq({ dn, uuid }) {
+    return new Promise((resolve, reject) => {
+      const keyname = `${this.app.config.filePath.key}${uuid}.key`;
+      const reqname = `${this.app.config.filePath.req}${uuid}.pem`;
+      // 创建申请书
+      exec(`pki --req --type priv --in ${keyname} \ --dn ${dn} \ --outform pem`, function(error, stdout) {
+        if (error) {
+          reject(error);
+        }
+        fs.writeFile(reqname, stdout, {}, function(err) {
+          if (err) {
+            fs.unlink(keyname, function(err) {
+              if (err) {
+                reject(err);
+              }
+            });
+            reject(err);
+          }
+          resolve({ errmsg: '', errcode: 0 });
+        });
+      });
+    });
+  }
+  // 文件写入
+  async write({ filePath, str }) {
+    return new Promise((resolve, reject) => {
+      fs.writeFile(path.resolve(filePath), str, {}, function(err) {
+        if (err) {
+          reject(err);
+        }
+        resolve({ errmsg: '', errcode: 0 });
+      });
+    });
+  }
+  async filewrite({ filePath, stream }) {
+    return new Promise((resolve, reject) => {
+      const target = path.join(filePath);
+      const remoteFileStream = fs.createWriteStream(target);
+      stream.pipe(remoteFileStream);
+      let errFlag;
+      remoteFileStream.on('error', err => {
+        errFlag = true;
+        remoteFileStream.destroy();
+        reject(err);
+      });
+
+      remoteFileStream.on('finish', async () => {
+        if (errFlag) return;
+        resolve({ errcode: 0, errmsg: '' });
+      });
+    });
+  }
+  // 解析key
+  async keys({ target, password }) {
+    return new Promise((resolve, reject) => {
+      exec(`openssl pkcs12 -info -in ${target} -nodes -nocerts -password pass:${password}`, function(error, stdout) {
+        if (error) {
+          reject(error);
+        }
+        const srart = stdout.indexOf('-----BEGIN PRIVATE KEY-----');
+        const data = stdout.slice(srart, stdout.length);
+        resolve({ errcode: 0, errmsg: '', data });
+      });
+    });
+  }
+  // key格式转换
+  async transform({ files, target }) {
+    return new Promise((resolve, reject) => {
+      exec(`openssl pkcs8 -in ${this.app.config.filePath.key}${files}  -traditional -out ${this.app.config.filePath.key}${target} -nocrypt`, function(error, stdout) {
+        if (error) {
+          reject(error);
+        }
+        console.log(stdout);
+        resolve({ errcode: 0, errmsg: '', data: stdout });
+      });
+    });
+  }
+  // 解析证书
+  async certs({ target, password }) {
+    return new Promise((resolve, reject) => {
+      exec(`openssl pkcs12 -info -in ${target} -password pass:${password} -nokeys -clcerts`, function(error, stdout) {
+        if (error) {
+          reject(error);
+        }
+        const srart = stdout.indexOf('-----BEGIN CERTIFICATE-----');
+        const data = stdout.slice(srart, stdout.length);
+        resolve({ errcode: 0, errmsg: '', data });
+      });
+    });
+  }
+  // 权限验证
+  async login() {
+    const { userName } = this.ctx.state.user;
+    if (userName !== 'admin') {
+      return { errcode: 403, errmsg: '没有权限' };
+    }
+    return { errcode: 0, errmsg: '' };
+
+  }
+  // 开机运行dhcp
+  async dhcp({ type }) {
+    return new Promise((resolve, reject) => {
+      exec(`systemctl ${type} isc-dhcp-server.service`, function(error) {
+        if (error) {
+          reject(error);
+        }
+        resolve({ errcode: 0, errmsg: '' });
+      });
+    });
+  }
+  // 开机运行openvpn  enable 开机运行   disable 开机不运行  restart 重新启动服务
+  async openvpn({ type }) {
+    return new Promise((resolve, reject) => {
+      exec(`systemctl ${type} openvpn.service`, function(error) {
+        if (error) {
+          reject(error);
+        }
+        resolve({ errcode: 0, errmsg: '' });
+      });
+    });
+  }
+  // ipseca
+  async ipsecas({ type }) {
+    return new Promise((resolve, reject) => {
+      exec(`systemctl ${type} strongswan-swanctl`, function(error) {
+        if (error) {
+          reject(error);
+        }
+        resolve({ errcode: 0, errmsg: '' });
+      });
+    });
+  }
+  // 重启服务器
+  async reboot() {
+    return new Promise((resolve, reject) => {
+      exec('reboot', function(error) {
+        if (error) {
+          reject(error);
+        }
+        resolve({ errcode: 0, errmsg: '' });
+      });
+    });
+  }
+}
+
+module.exports = FileService;

+ 10 - 0
app/view/dhcp.nj

@@ -0,0 +1,10 @@
+option domain-name "example.org";
+option domain-name-servers 114.114.114.114;
+default-lease-time 600;
+max-lease-time 7200;
+subnet {{ addressTow }}.0 netmask 255.255.255.0 {
+  range {{ addressTow }}.{{ start }} {{ addressTow }}.{{ end }};
+  option subnet-mask 255.255.255.0;
+  option routers {{ address }};
+  option broadcast-address {{ addressTow }}.255;
+}

+ 13 - 0
app/view/ipsecalog.nj

@@ -0,0 +1,13 @@
+charon {
+  filelog {
+    charon {
+      path = /var/log/charon.log
+      time_format = %b %e %T
+      ike_name = yes
+      append = no
+      default = {{ loglevel }}
+      flush_line = yes
+    }
+  }
+}
+

+ 23 - 0
app/view/ipsecavpn.nj

@@ -0,0 +1,23 @@
+connections {
+	home {
+		version = 1
+		remote_addrs = {{ address }}
+		proposals = sm4-sm3-modpnone
+		vips = 0.0.0.0
+		local {
+			auth = pubkey
+			certs = {{ certpath }}
+		}
+		remote {
+			auth = pubkey
+		}	
+		children {
+			home {
+				remote_ts  = {{ addressTow }}/{{ digit }}
+				start_action = start
+				esp_proposals = sm4-sm3-modpnone
+			}
+		}
+	}
+}
+

+ 26 - 0
app/view/ipsecavpnservice.nj

@@ -0,0 +1,26 @@
+connections {
+	rw {
+		version = 1
+		pools = rw_pool
+		proposals = sm4-sm3-modpnone
+		local {
+			auth = pubkey
+			certs = {{ certpath }}
+		}
+		remote {
+			auth = pubkey
+		}
+		children {
+			net-net {
+				local_ts  = {{ address }}/{{ digit }}
+				esp_proposals = sm4-sm3-modpnone
+			}
+		}
+	}
+}
+pools {
+	rw_pool {
+		addrs = {{ addressTow }}/{{ digitTow }}
+	}
+}
+

+ 13 - 0
app/view/lan.nj

@@ -0,0 +1,13 @@
+auto br-lan
+iface br-lan inet static
+    pre-up ifconfig lan0 up
+    pre-up ifconfig lan1 up
+    pre-up ifconfig lan2 up
+    pre-up ifconfig lan3 up
+    address {{ address }}
+    netmask 255.255.255.0
+    broadcast {{ addressTow }}.255
+    bridge_ports lan0
+    bridge_ports lan1
+    bridge_ports lan2
+    bridge_ports lan3

+ 28 - 0
app/view/sslvpn.nj

@@ -0,0 +1,28 @@
+client
+
+dev tun
+
+data-ciphers SMS4-CBC:SMS4-CFB:SMS4-OFB
+cipher SMS4-CBC
+auth SM3
+auth-nocache
+tls-version-min 1.1
+tls-version-max 1.2
+tls-cipher ECDHE-SM2-WITH-SMS4-GCM-SM3:ECDHE-SM2-WITH-SMS4-SM3:SM2-WITH-SMS4-SM3:SM2DHE-WITH-SMS4-SM3
+
+#compress lzo
+
+resolv-retry infinite
+script-security 2
+nobind
+persist-key
+persist-tun
+mute-replay-warnings
+log /var/log/openvpn.log
+
+proto {{ agreement }}
+remote {{ address }} {{ port }}
+ca {{ capath }}
+cert {{ certpath }}
+key {{ keys }}
+verb {{ loglevel }}

+ 37 - 0
app/view/sslvpnservice.nj

@@ -0,0 +1,37 @@
+dev tun
+
+dh /etc/openvpn/server/dh.pem
+
+#crl-verify /etc/openvpn/server/crl.pem
+#push "dhcp-option DNS 84.200.69.80"
+#push "dhcp-option DNS 84.200.70.40"
+
+duplicate-cn
+
+data-ciphers SMS4-CBC:SMS4-CFB:SMS4-OFB
+cipher SMS4-CBC
+auth SM3
+auth-nocache
+tls-version-min 1.1
+tls-version-max 1.2
+tls-cipher ECDHE-SM2-WITH-SMS4-GCM-SM3:ECDHE-SM2-WITH-SMS4-SM3:SM2-WITH-SMS4-SM3:SM2DHE-WITH-SMS4-SM3
+
+keepalive 20 60
+persist-key
+persist-tun
+#comp-lzo yes
+daemon
+#user nobody
+#group nobody
+
+log-append /var/log/openvpn.log
+
+
+proto  {{ agreement  }}
+server  {{ address }}  {{ netmask }}
+port  {{ port }}
+ca  {{ capath }}
+cert  {{ certpath }}
+key  {{ keys }}
+push "route  {{ routerAddress  }}  {{ routerNetmask  }}"
+verb  {{ loglevel  }}

+ 14 - 0
app/view/wan.nj

@@ -0,0 +1,14 @@
+{% if type === 1 %}
+auto wan
+iface wan inet static
+    pre-up ifconfig eth0 up
+    address {{ address }}
+    netmask {{ netmask }}
+    gateway {{ gateway }}
+    dns-nameservers 114.114.114.114
+{% else %}
+auto wan
+iface wan inet dhcp
+    pre-up ifconfig eth0 up
+    dns-nameservers 114.114.114.114
+{% endif %}

+ 14 - 0
appveyor.yml

@@ -0,0 +1,14 @@
+environment:
+  matrix:
+    - nodejs_version: '10'
+
+install:
+  - ps: Install-Product node $env:nodejs_version
+  - npm i npminstall && node_modules\.bin\npminstall
+
+test_script:
+  - node --version
+  - npm --version
+  - npm run test
+
+build: off

+ 75 - 0
config/config.default.js

@@ -0,0 +1,75 @@
+/* eslint valid-jsdoc: "off" */
+
+'use strict';
+/**
+ * @param {Egg.EggAppInfo} appInfo app info
+ */
+module.exports = appInfo => {
+  /**
+   * built-in config
+   * @type {Egg.EggAppConfig}
+   **/
+  const config = exports = {};
+  exports.logger = {
+    level: 'ERROR',
+  };
+  // use for cookie sign key, should change to your own and keep security
+  config.keys = appInfo.name + '_1607560704634_7850';
+
+  // add your middleware config here
+  config.middleware = [];
+  config.security = {
+    csrf: {
+      enable: false,
+      ignoreJSON: true,
+    },
+    // 允许访问接口的白名单
+    // domainWhiteList: [ 'http://localhost:8080' ],
+  };
+  config.cluster = {
+    listen: {
+      path: '',
+      port: 7001,
+      // hostname: '0.0.0.0',
+    },
+  };
+  config.view = {
+    mapping: {
+      '.nj': 'nunjucks',
+    },
+  };
+  config.assets = {
+    publicPath: '/public/',
+  };
+  config.multipart = {
+    mode: 'stream',
+    whitelist: [ '.pem', '.crt', '.der', '.cer', '.pfx', '.p12', '.jks' ],
+  };
+  config.jwt = {
+    secret: '123456',
+  };
+  config.filePath = {
+    configJson: '/etc/vpn/config.json',
+    ca: '/ipsec/etc/swanctl/x509ca/',
+    cert: '/ipsec/etc/swanctl/x509/',
+    key: '/ipsec/etc/swanctl/private/',
+    req: '/etc/vpn/req/',
+    p12: '/ipsec/etc/swanctl/pkcs12/',
+    ipsec: '/ipsec/etc/swanctl/conf.d/client.conf',
+    ipseclog: '/ipsec/etc/strongswan.d/charon-logging.conf',
+    ipsecservice: '/ipsec/etc/swanctl/conf.d/server.conf',
+    sslvpn: '/etc/openvpn/openvpn.conf',
+    dhcpd: '/etc/dhcp/dhcpd.conf',
+    wan: '/etc/network/interfaces.d/wan',
+    lan: '/etc/network/interfaces.d/br-lan',
+  };
+  // add your user config here
+  const userConfig = {
+    // myAppName: 'egg',
+  };
+
+  return {
+    ...config,
+    ...userConfig,
+  };
+};

+ 21 - 0
config/plugin.js

@@ -0,0 +1,21 @@
+'use strict';
+
+/** @type Egg.EggPlugin */
+module.exports = {
+  // had enabled by egg
+  // static: {
+  //   enable: true,
+  // }
+  jwt: {
+    enable: true,
+    package: 'egg-jwt',
+  },
+  static: {
+    enable: true,
+  },
+  nunjucks: {
+    enable: true,
+    package: 'egg-view-nunjucks',
+  },
+};
+

+ 5 - 0
jsconfig.json

@@ -0,0 +1,5 @@
+{
+  "include": [
+    "**/*"
+  ]
+}

+ 22 - 0
node_cache/_logs/2020-12-12T06_00_03_533Z-debug.log

@@ -0,0 +1,22 @@
+0 info it worked if it ends with ok
+1 verbose cli [ '/mnt/d/linux-node/bin/node', '/usr/bin/npm', 'run', 'serve' ]
+2 info using npm@6.14.8
+3 info using node@v14.15.1
+4 verbose stack Error: missing script: serve
+4 verbose stack     at run (/mnt/d/linux-node/lib/node_modules/npm/lib/run-script.js:155:19)
+4 verbose stack     at /mnt/d/linux-node/lib/node_modules/npm/lib/run-script.js:63:5
+4 verbose stack     at /mnt/d/linux-node/lib/node_modules/npm/node_modules/read-package-json/read-json.js:116:5
+4 verbose stack     at /mnt/d/linux-node/lib/node_modules/npm/node_modules/read-package-json/read-json.js:436:5
+4 verbose stack     at checkBinReferences_ (/mnt/d/linux-node/lib/node_modules/npm/node_modules/read-package-json/read-json.js:391:45)
+4 verbose stack     at final (/mnt/d/linux-node/lib/node_modules/npm/node_modules/read-package-json/read-json.js:434:3)
+4 verbose stack     at then (/mnt/d/linux-node/lib/node_modules/npm/node_modules/read-package-json/read-json.js:161:5)
+4 verbose stack     at /mnt/d/linux-node/lib/node_modules/npm/node_modules/read-package-json/read-json.js:281:12
+4 verbose stack     at /mnt/d/linux-node/lib/node_modules/npm/node_modules/graceful-fs/graceful-fs.js:123:16
+4 verbose stack     at FSReqCallback.readFileAfterClose [as oncomplete] (internal/fs/read_file_context.js:63:3)
+5 verbose cwd /mnt/c/Users/10428/Desktop/VPN后台管理/vpnserve
+6 verbose Linux 4.4.0-18362-Microsoft
+7 verbose argv "/mnt/d/linux-node/bin/node" "/usr/bin/npm" "run" "serve"
+8 verbose node v14.15.1
+9 verbose npm  v6.14.8
+10 error missing script: serve
+11 verbose exit [ 1, true ]

+ 15 - 0
node_cache/_logs/2020-12-14T06_59_18_276Z-debug.log

@@ -0,0 +1,15 @@
+0 info it worked if it ends with ok
+1 verbose cli [ '/mnt/d/linux-node/bin/node', '/usr/bin/npm', 'run', 'dev' ]
+2 info using npm@6.14.8
+3 info using node@v14.15.1
+4 verbose run-script [ 'predev', 'dev', 'postdev' ]
+5 info lifecycle vpnserve@1.0.0~predev: vpnserve@1.0.0
+6 info lifecycle vpnserve@1.0.0~dev: vpnserve@1.0.0
+7 verbose lifecycle vpnserve@1.0.0~dev: unsafe-perm in lifecycle true
+8 verbose lifecycle vpnserve@1.0.0~dev: PATH: /mnt/d/linux-node/lib/node_modules/npm/node_modules/npm-lifecycle/node-gyp-bin:/mnt/c/Users/10428/Desktop/VPN后台管理/vpnserve/node_modules/.bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games
+9 verbose lifecycle vpnserve@1.0.0~dev: CWD: /mnt/c/Users/10428/Desktop/VPN后台管理/vpnserve
+10 silly lifecycle vpnserve@1.0.0~dev: Args: [ '-c', 'egg-bin dev' ]
+11 timing npm Completed in 11974833ms
+12 error cb() never called!
+13 error This is an error with npm itself. Please report this error at:
+14 error <https://npm.community>

+ 15 - 0
node_cache/_logs/2020-12-16T03_47_08_002Z-debug.log

@@ -0,0 +1,15 @@
+0 info it worked if it ends with ok
+1 verbose cli [ '/mnt/d/linux-node/bin/node', '/usr/bin/npm', 'run', 'dev' ]
+2 info using npm@6.14.8
+3 info using node@v14.15.1
+4 verbose run-script [ 'predev', 'dev', 'postdev' ]
+5 info lifecycle vpnserve@1.0.0~predev: vpnserve@1.0.0
+6 info lifecycle vpnserve@1.0.0~dev: vpnserve@1.0.0
+7 verbose lifecycle vpnserve@1.0.0~dev: unsafe-perm in lifecycle true
+8 verbose lifecycle vpnserve@1.0.0~dev: PATH: /mnt/d/linux-node/lib/node_modules/npm/node_modules/npm-lifecycle/node-gyp-bin:/mnt/c/Users/10428/Desktop/VPN后台管理/vpnserve/node_modules/.bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/usr/local/ipsec/bin
+9 verbose lifecycle vpnserve@1.0.0~dev: CWD: /mnt/c/Users/10428/Desktop/VPN后台管理/vpnserve
+10 silly lifecycle vpnserve@1.0.0~dev: Args: [ '-c', 'egg-bin dev' ]
+11 timing npm Completed in 6439005ms
+12 error cb() never called!
+13 error This is an error with npm itself. Please report this error at:
+14 error <https://npm.community>

+ 15 - 0
node_cache/_logs/2020-12-17T06_03_46_278Z-debug.log

@@ -0,0 +1,15 @@
+0 info it worked if it ends with ok
+1 verbose cli [ '/mnt/d/linux-node/bin/node', '/usr/bin/npm', 'run', 'dev' ]
+2 info using npm@6.14.8
+3 info using node@v14.15.1
+4 verbose run-script [ 'predev', 'dev', 'postdev' ]
+5 info lifecycle vpnserve@1.0.0~predev: vpnserve@1.0.0
+6 info lifecycle vpnserve@1.0.0~dev: vpnserve@1.0.0
+7 verbose lifecycle vpnserve@1.0.0~dev: unsafe-perm in lifecycle true
+8 verbose lifecycle vpnserve@1.0.0~dev: PATH: /mnt/d/linux-node/lib/node_modules/npm/node_modules/npm-lifecycle/node-gyp-bin:/mnt/c/Users/10428/Desktop/VPN后台管理/vpnserve/node_modules/.bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/usr/local/ipsec/bin
+9 verbose lifecycle vpnserve@1.0.0~dev: CWD: /mnt/c/Users/10428/Desktop/VPN后台管理/vpnserve
+10 silly lifecycle vpnserve@1.0.0~dev: Args: [ '-c', 'egg-bin dev' ]
+11 timing npm Completed in 123137ms
+12 error cb() never called!
+13 error This is an error with npm itself. Please report this error at:
+14 error <https://npm.community>

+ 15 - 0
node_cache/_logs/2020-12-22T07_51_58_271Z-debug.log

@@ -0,0 +1,15 @@
+0 info it worked if it ends with ok
+1 verbose cli [ '/mnt/d/linux-node/bin/node', '/usr/bin/npm', 'run', 'dev' ]
+2 info using npm@6.14.8
+3 info using node@v14.15.1
+4 verbose run-script [ 'predev', 'dev', 'postdev' ]
+5 info lifecycle vpnserve@1.0.0~predev: vpnserve@1.0.0
+6 info lifecycle vpnserve@1.0.0~dev: vpnserve@1.0.0
+7 verbose lifecycle vpnserve@1.0.0~dev: unsafe-perm in lifecycle true
+8 verbose lifecycle vpnserve@1.0.0~dev: PATH: /mnt/d/linux-node/lib/node_modules/npm/node_modules/npm-lifecycle/node-gyp-bin:/mnt/c/Users/10428/Desktop/VPN后台管理/vpnserve/node_modules/.bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/ipsec/bin
+9 verbose lifecycle vpnserve@1.0.0~dev: CWD: /mnt/c/Users/10428/Desktop/VPN后台管理/vpnserve
+10 silly lifecycle vpnserve@1.0.0~dev: Args: [ '-c', 'egg-bin dev' ]
+11 timing npm Completed in 128453ms
+12 error cb() never called!
+13 error This is an error with npm itself. Please report this error at:
+14 error <https://npm.community>

+ 34 - 0
node_cache/_logs/2020-12-23T02_17_23_381Z-debug.log

@@ -0,0 +1,34 @@
+0 info it worked if it ends with ok
+1 verbose cli [ '/mnt/d/linux-node/bin/node', '/usr/bin/npm', 'run', 'dev' ]
+2 info using npm@6.14.8
+3 info using node@v14.15.1
+4 verbose run-script [ 'predev', 'dev', 'postdev' ]
+5 info lifecycle vpnserve@1.0.0~predev: vpnserve@1.0.0
+6 info lifecycle vpnserve@1.0.0~dev: vpnserve@1.0.0
+7 verbose lifecycle vpnserve@1.0.0~dev: unsafe-perm in lifecycle true
+8 verbose lifecycle vpnserve@1.0.0~dev: PATH: /mnt/d/linux-node/lib/node_modules/npm/node_modules/npm-lifecycle/node-gyp-bin:/mnt/c/Users/10428/Desktop/VPN后台管理/vpnserve/node_modules/.bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/ipsec/bin
+9 verbose lifecycle vpnserve@1.0.0~dev: CWD: /mnt/c/Users/10428/Desktop/VPN后台管理/vpnserve
+10 silly lifecycle vpnserve@1.0.0~dev: Args: [ '-c', 'egg-bin dev' ]
+11 silly lifecycle vpnserve@1.0.0~dev: Returned: code: 1  signal: null
+12 info lifecycle vpnserve@1.0.0~dev: Failed to exec dev script
+13 verbose stack Error: vpnserve@1.0.0 dev: `egg-bin dev`
+13 verbose stack Exit status 1
+13 verbose stack     at EventEmitter.<anonymous> (/mnt/d/linux-node/lib/node_modules/npm/node_modules/npm-lifecycle/index.js:332:16)
+13 verbose stack     at EventEmitter.emit (events.js:315:20)
+13 verbose stack     at ChildProcess.<anonymous> (/mnt/d/linux-node/lib/node_modules/npm/node_modules/npm-lifecycle/lib/spawn.js:55:14)
+13 verbose stack     at ChildProcess.emit (events.js:315:20)
+13 verbose stack     at maybeClose (internal/child_process.js:1048:16)
+13 verbose stack     at Process.ChildProcess._handle.onexit (internal/child_process.js:288:5)
+14 verbose pkgid vpnserve@1.0.0
+15 verbose cwd /mnt/c/Users/10428/Desktop/VPN后台管理/vpnserve
+16 verbose Linux 4.4.0-18362-Microsoft
+17 verbose argv "/mnt/d/linux-node/bin/node" "/usr/bin/npm" "run" "dev"
+18 verbose node v14.15.1
+19 verbose npm  v6.14.8
+20 error code ELIFECYCLE
+21 error errno 1
+22 error vpnserve@1.0.0 dev: `egg-bin dev`
+22 error Exit status 1
+23 error Failed at the vpnserve@1.0.0 dev script.
+23 error This is probably not a problem with npm. There is likely additional logging output above.
+24 verbose exit [ 1, true ]

+ 15 - 0
node_cache/_logs/2020-12-24T02_13_14_176Z-debug.log

@@ -0,0 +1,15 @@
+0 info it worked if it ends with ok
+1 verbose cli [ '/mnt/d/linux-node/bin/node', '/usr/bin/npm', 'run', 'dev' ]
+2 info using npm@6.14.8
+3 info using node@v14.15.1
+4 verbose run-script [ 'predev', 'dev', 'postdev' ]
+5 info lifecycle vpnserve@1.0.0~predev: vpnserve@1.0.0
+6 info lifecycle vpnserve@1.0.0~dev: vpnserve@1.0.0
+7 verbose lifecycle vpnserve@1.0.0~dev: unsafe-perm in lifecycle true
+8 verbose lifecycle vpnserve@1.0.0~dev: PATH: /mnt/d/linux-node/lib/node_modules/npm/node_modules/npm-lifecycle/node-gyp-bin:/mnt/c/Users/10428/Desktop/VPN后台管理/vpnserve/node_modules/.bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/ipsec/bin
+9 verbose lifecycle vpnserve@1.0.0~dev: CWD: /mnt/c/Users/10428/Desktop/VPN后台管理/vpnserve
+10 silly lifecycle vpnserve@1.0.0~dev: Args: [ '-c', 'egg-bin dev' ]
+11 timing npm Completed in 7123737ms
+12 error cb() never called!
+13 error This is an error with npm itself. Please report this error at:
+14 error <https://npm.community>

+ 15 - 0
node_cache/_logs/2020-12-28T05_33_37_064Z-debug.log

@@ -0,0 +1,15 @@
+0 info it worked if it ends with ok
+1 verbose cli [ '/mnt/d/linux-node/bin/node', '/usr/bin/npm', 'run', 'dev' ]
+2 info using npm@6.14.8
+3 info using node@v14.15.1
+4 verbose run-script [ 'predev', 'dev', 'postdev' ]
+5 info lifecycle vpnserve@1.0.0~predev: vpnserve@1.0.0
+6 info lifecycle vpnserve@1.0.0~dev: vpnserve@1.0.0
+7 verbose lifecycle vpnserve@1.0.0~dev: unsafe-perm in lifecycle true
+8 verbose lifecycle vpnserve@1.0.0~dev: PATH: /mnt/d/linux-node/lib/node_modules/npm/node_modules/npm-lifecycle/node-gyp-bin:/mnt/c/Users/10428/Desktop/VPN后台管理/vpnserve/node_modules/.bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/ipsec/bin
+9 verbose lifecycle vpnserve@1.0.0~dev: CWD: /mnt/c/Users/10428/Desktop/VPN后台管理/vpnserve
+10 silly lifecycle vpnserve@1.0.0~dev: Args: [ '-c', 'egg-bin dev' ]
+11 timing npm Completed in 8641410ms
+12 error cb() never called!
+13 error This is an error with npm itself. Please report this error at:
+14 error <https://npm.community>

+ 49 - 0
package.json

@@ -0,0 +1,49 @@
+{
+  "name": "vpnserve",
+  "version": "1.0.0",
+  "description": "",
+  "private": true,
+  "egg": {
+    "declarations": true
+  },
+  "dependencies": {
+    "egg": "^2.15.1",
+    "egg-jwt": "^3.1.7",
+    "egg-scripts": "^2.11.0",
+    "egg-view-nunjucks": "^2.2.0",
+    "uuid": "^8.3.2"
+  },
+  "devDependencies": {
+    "autod": "^3.0.1",
+    "autod-egg": "^1.1.0",
+    "egg-bin": "^4.11.0",
+    "egg-ci": "^1.11.0",
+    "egg-mock": "^3.21.0",
+    "eslint": "^5.13.0",
+    "eslint-config-egg": "^7.1.0"
+  },
+  "engines": {
+    "node": ">=10.0.0"
+  },
+  "scripts": {
+    "start": "egg-scripts start --daemon --title=egg-server-vpnserve",
+    "stop": "egg-scripts stop --title=egg-server-vpnserve",
+    "dev": "egg-bin dev",
+    "debug": "egg-bin debug",
+    "test": "npm run lint -- --fix && npm run test-local",
+    "test-local": "egg-bin test",
+    "cov": "egg-bin cov",
+    "lint": "eslint .",
+    "ci": "npm run lint && npm run cov",
+    "autod": "autod"
+  },
+  "ci": {
+    "version": "10"
+  },
+  "repository": {
+    "type": "git",
+    "url": ""
+  },
+  "author": "",
+  "license": "MIT"
+}

+ 20 - 0
test/app/controller/home.test.js

@@ -0,0 +1,20 @@
+'use strict';
+
+const { app, assert } = require('egg-mock/bootstrap');
+
+describe('test/app/controller/home.test.js', () => {
+  it('should assert', () => {
+    const pkg = require('../../../package.json');
+    assert(app.config.keys.startsWith(pkg.name));
+
+    // const ctx = app.mockContext({});
+    // yield ctx.service.xx();
+  });
+
+  it('should GET /', () => {
+    return app.httpRequest()
+      .get('/')
+      .expect('hi, egg')
+      .expect(200);
+  });
+});