使用electron-vue + frp 开发一款穿透软件

2022-06-16 19:07:46 浏览数 (1)

注意:下面的步骤都是要基于服务端&客户端已经能实现内网穿透,如果没有,请移步:Linux环境搭建frp实现内网穿透


准备工作:

使用electron-vue框架,跑起来项目, 参考地址: https://simulatedgreg.gitbooks.io/electron-vue/content/cn/ 跑起来长这样

服务端&客户端已经能实现内网穿透,参考文章:http://lvsige.top/archives/19

如果以上两项都完成了,那么请继续~


捋一下思路

一个穿透软件,需要具备的能力:用户安装软件后,只需要填写本地端口号以及期望的域名,点击连接,即可使用域名访问本地文件。

  1. 服务端是不用管的,已经配置ok
  2. 客户端需要把解压后的frp文件夹,让用户能随心修改。(不能说每个用户使用此软件时,都需要在本地下载一个frp压缩包)
  3. 能够在软件里启动子进程。 ./frpc -c ./frpc.ini 这个命令应该自动完成。

实现方法

需要读写frp/frpc.ini文件里的内容

用到nodejs里的ini, fs, path模块。

需要启动frp

用nodejs里 child_process 模块。child_process文档


具体代码

把解压后的frp文件夹放在electron-vue项目里

在主进程里:

代码语言:javascript复制
const ini = require('ini')
const path = require('path')
const fs = require('fs')

let appPath = path.resolve(__dirname, '../../')
let filePath = path.join(appPath, 'frp', 'frpc.ini')
let config = null
// 开始读取数据
fs.readFile(filePath, (err, data) => {
  if (data) {
    config = ini.parse(data.toString())
    app.config = config
  }
}) 

点击"连接"时, 能够修改frpc.ini

代码语言:javascript复制
// 写入数据
function writeConfig(config) {
  var iniObj = {
    common: {
      server_addr: 'x.x.x.x',
      server_port: 7000,
    },
    web: {
      type: 'http',
      local_port: config.port,
      custom_domains: `${config.hostname}${config.thost || '.lvsige.top'}`,
    },
  }
  let iniStr = ini.encode(iniObj)
  fs.writeFileSync(filePath, iniStr)
}

可以读取写入frpc.ini之后, 就要建立连接了

nodejs里的子进程模块 http://nodejs.cn/api/child_process.html

代码语言:javascript复制
const exec = require('child_process').exec

ipcMain.on('connectEvent', (event, arg) => {
  writeConfig(arg)
  zlog.info('接收到参数 开始建立连接')
  let filePath = path.join(appPath, 'frp')
  workerProcess = exec(
    `cd  ${filePath} 
      chmod 755 *
      ./frpc -c ./frpc.ini 
      `,
    {}
  )
  // 给当前目录所有文件修改权限为755
  // 打印正常的后台可执行程序输出
  workerProcess.stdout.on('data', (data) => {
    event.sender.send('okAllInfo', data)
    zlog.info(data, '打印正常的后台可执行程序输出')
  })
  // 打印错误的后台可执行程序输出
  workerProcess.stderr.on('data', (data) => {
    zlog.info(data, '打印错误的后台可执行程序输出')
  })
  // 退出之后的输出
  workerProcess.on('exit', (code) => {
    zlog.info('process exit', code)
  })
})

关闭断开连接时

代码语言:javascript复制
// 退出
ipcMain.on('close', (event, arg) => {
  zlog.info('断开连接, 收到信号了')
  exec('ps -ef|grep frp', function (err, stdout, stderr) { 
    stdout.split('n').filter(function (line) { 
      var p = line.trim().split(/s /) 
      var address = p[1] 
      if (
        address !== undefined &&
        address !== 'PID' &&
        p.some((item) => {
          return item === './frpc.ini'
        })
      ) {  
        exec('kill '   address, function (err, stdout, stderr) {
          if (err) {
            return zlog.info('杀死进程失败!!')
          }
          event.sender.send('killProcess')
          zlog.info('杀死进程成功')
        })
      }
    })
  })
})

0 人点赞