[关闭]
@code33 2019-07-01T09:50:24.000000Z 字数 11815 阅读 1419

迪联技术文档-内网穿透技术 1.4

frp ngrok 技术文档

modify by jyo on 2018-09-15
modify by jyo on 2018-07
modify by jyo on 2018-06-08
create by Bunm Jyo on 2017-05-13
contact code0515@gmail.com



概述

应用场景:
解决内网无固定IP,需要向外网开放服务端口请求的功能需求
用于外网向内网请求,而内网无需在路由器配置开放及映射端口
目前技术已有两种实现 ngrok 和 frp

原理:
外网需要一服务器长连接FRPSERVICE服务端,与内网保持长链接维持心跳,并与之通信,请求数据通过长连接通道实现,之间的通信以长连接的socks方式实现

注意:
但若是该穿透通道服务需要与指定域名进行绑定,则需对其进行特殊的headers HOST处理,以便让FRPSERVICE可识别到具体哪项通道服务

  1. # 新建一个伪造header Host 的nginx端口服务
  2. server {
  3. listen 10335;
  4. server_name _;
  5. charset utf-8;
  6. location / {
  7. proxy_set_header X-Real-IP $remote_addr;
  8. proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  9. # 伪造header Host 的nginx端口服务
  10. proxy_set_header Host bessnodeprepro.frp.1000hou.com:51901;
  11. #proxy_set_header X-NginX-Proxy true;
  12. proxy_pass http://bessnodeprepro.frp.1000hou.com:51901/;
  13. #health_check;
  14. add_header Access-Control-Allow-Headers X-Requested-With;
  15. add_header 'Access-Control-Allow-Credentials' 'true';
  16. add_header 'Access-Control-Allow-Methods' GET,POST,PUT,OPTIONS,DELETE,HEAD;
  17. proxy_redirect off;
  18. }
  19. }
  20. # 做成一个流服务映射
  21. upstream bessnodepreprorls-frp {
  22. server 127.0.0.1:10335;
  23. }
  24. server {
  25. listen 443;
  26. server_name hdzbessmana.1000hou.com;
  27. ssl on;
  28. ssl_certificate /etc/nginx/CA/hdzbessmana/hdzbessmana2018.pem;
  29. ssl_certificate_key /etc/nginx/CA/hdzbessmana/hdzbessmana2018.key;
  30. ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
  31. ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
  32. ssl_prefer_server_ciphers on;
  33. access_log /var/log/nginx/hdzbessmana.ssl.access.log;
  34. error_log /var/log/nginx/hdzbessmana.ssl.error.log;
  35. location /.well-known/pki-validation/fileauth.txt {
  36. proxy_pass http://hdzbessmana-ssl/;
  37. }
  38. location ~ ^/v1.1.2/bsmana/?((?<=/).*)?$ {
  39. proxy_set_header X-Real-IP $remote_addr;
  40. proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  41. proxy_set_header Host $proxy_host;
  42. proxy_set_header X-NginX-Proxy true;
  43. proxy_set_header versionc '1.1.2';
  44. add_header versionc '1.1.2';
  45. # txc
  46. #proxy_pass http://bessnodepreprotxc-frp/$1$is_args$args;
  47. #release 这里就是代理到穿透通道nginx流服务
  48. proxy_pass http://bessnodepreprorls-frp/$1$is_args$args;
  49. #add_header Content-Type 'application/json; charset=utf-8';
  50. proxy_redirect off;
  51. }
  52. }

libqtSS

一款代理服务应用,通过它可以走宿主机的流量
输出为TCP协议

安装

windows-32 http://xyzsetup.dlhis.com/shadowsocks-libqss-v1.9.0-win32.7z
windows-64 http://xyzsetup.dlhis.com/shadowsocks-libqss-v1.9.0-win64.7z

运行

配置参数
保存为config.json

  1. {
  2. "server":"0.0.0.0",
  3. "server_port":14201,
  4. "password":"523186",
  5. "timeout":300,
  6. "method":"rc4-md5",
  7. "fast_open":false,
  8. "workers": 2
  9. }

运行命令附带参数

  1. shadowsocks-libqss.exe -c config.json -S

frp

以下版本基于frp 0.9.3

支持 tcp, udp, http, https 等协议类型,并且 web 服务支持根据域名进行路由转发。

frp-架构

frp-a.png-10.4kB

frp-安装 & 运行

frp-下载

源码 http://xyzsetup.dlhis.com/frp-0.9.3-source.tar.gz
arm http://xyzsetup.dlhis.com/frp_0.9.3_linux_arm.tar.gz
windows-64 http://xyzsetup.dlhis.com/frp_0.9.3_windows_amd64.zip
windows-32 http://xyzsetup.dlhis.com/frp_0.9.3_windows_386.zip
linux-64 http://xyzsetup.dlhis.com/frp_0.9.3_linux_amd64.tar.gz

frp-操作

根据自己的操作系统下载对应的包
还有更多版本 可以查看这里 Release

解压后 进入文件夹,可以看到这几个文件 (以下在Linux 64bit上操作举例)

其中无后缀的为可执行文件,ini为配置文件

服务端开启服务执行

  1. ./frps -c frps.ini

客户端开启服务执行

  1. ./frpc -c frpc.ini

frp-配置 & 说明

服务端ini配置参数说明

  1. # 服务器组件连接配置
  2. # [common] is integral section
  3. [common]
  4. # A literal address or host name for IPv6 must be enclosed
  5. # in square brackets, as in "[::1]:80", "[ipv6-host]:http" or "[ipv6-host%zone]:80"
  6. # 允许的地址
  7. bind_addr = 0.0.0.0
  8. # 服务端供客户端连接的握手端口
  9. bind_port = 7000
  10. # if you want to support virtual host, you must set the http port for listening (optional)
  11. # 若是要对http服务支持,则必须配置该项目
  12. # vhost_http_port意为服务端对外开放的http协议的端口
  13. vhost_http_port = 80
  14. # vhost_https_port意为服务端对外开放的https协议的端口
  15. vhost_https_port = 443
  16. # 控制面板管理端口
  17. # if you want to configure or reload frps by dashboard, dashboard_port must be set
  18. dashboard_port = 7500
  19. # 控制面板用户名及口令
  20. # dashboard user and pwd for basic auth protect, if not set, both default value is admin
  21. dashboard_user = admin
  22. dashboard_pwd = admin
  23. # dashboard assets directory(only for debug mode)
  24. # assets_dir = ./static
  25. # console or real logFile path like ./frps.log
  26. # 日志文件路径
  27. log_file = ./frps.log
  28. # debug, info, warn, error
  29. # 日志级别
  30. log_level = info
  31. # 保留日志天数
  32. log_max_days = 3
  33. # if you enable privilege mode, frpc can create a proxy without pre-configure in frps when privilege_token is correct
  34. # 特权服务模式,无需对服务端配置文件变更,即可接收来自于客户端的配置增加及变更,令服务端接收其配置方案并生效(如新增一个http通道即可直接在客户端新增一个[web-someone]配置即可)
  35. privilege_mode = true
  36. privilege_token = 12345678
  37. # heartbeat configure, it's not recommended to modify the default value
  38. # the default value of heartbeat_timeout is 30
  39. # 心跳时间,默认30s
  40. # heartbeat_timeout = 30
  41. # 特权服务允许的端口范围
  42. # only allow frpc to bind ports you list, if you set nothing, there won't be any limit
  43. privilege_allow_ports = 2000-3000,3001,3003,4000-60000
  44. # pool_count in each proxy will change to max_pool_count if they exceed the maximum value
  45. # 连接池通道数量
  46. max_pool_count = 100
  47. # authentication_timeout means the timeout interval (seconds) when the frpc connects frps
  48. # if authentication_timeout is zero, the time is not verified, default is 900s
  49. # 认证超时时间
  50. authentication_timeout = 900
  51. # if subdomain_host is not empty, you can set subdomain when type is http or https in frpc's configure file
  52. # when subdomain is test, the host used by routing is test.frps.com
  53. # 服务器绑定的域名,需要先在域名解析服务上配置
  54. # 这里建议使用泛域名符号 *
  55. # example: *.frps.com
  56. subdomain_host = frps.com
  57. # 以下是各个子服务代理通道连接的服务端静态配置方案,[name] 改配置内可自定义其名称
  58. # ssh is the proxy name, client will use this name and auth_token to connect to server
  59. [ssh]
  60. type = tcp
  61. auth_token = 123
  62. bind_addr = 0.0.0.0
  63. listen_port = 6000
  64. [dns]
  65. type = udp
  66. auth_token = 123
  67. bind_addr = 0.0.0.0
  68. listen_port = 5353
  69. [web01]
  70. # if type equals http, vhost_http_port must be set
  71. type = http
  72. auth_token = 123
  73. # if proxy type equals http, custom_domains must be set separated by commas
  74. custom_domains = web01.yourdomain.com,web01.yourdomain2.com
  75. [web02]
  76. # if type equals https, vhost_https_port must be set
  77. type = https
  78. auth_token = 123
  79. custom_domains = web02.yourdomain.com

客户端ini配置文件说明

  1. # [common] is integral section
  2. # 连接至服务器的配置项
  3. [common]
  4. # A literal address or host name for IPv6 must be enclosed
  5. # in square brackets, as in "[::1]:80", "[ipv6-host]:http" or "[ipv6-host%zone]:80"
  6. # 服务器地址 可以是IP 也可以是domain
  7. server_addr = 0.0.0.0
  8. # frp服务,服务连接端口
  9. server_port = 7000
  10. # if you want to connect frps by http proxy, you can set http_proxy here or in global environment variables
  11. # 通过代理的形式连接~好骚
  12. # http_proxy = http://user:pwd@192.168.1.128:8080
  13. # console or real logFile path like ./frpc.log
  14. # 客户端工作日志
  15. log_file = ./frpc.log
  16. # debug, info, warn, error
  17. log_level = info
  18. log_max_days = 3
  19. # for authentication
  20. # 身份token
  21. auth_token = 123
  22. # 特权token
  23. # for privilege mode
  24. privilege_token = 12345678
  25. # heartbeat configure, it's not recommended to modify the default value
  26. # the default value of heartbeat_interval is 10 and heartbeat_timeout is 30
  27. # 心跳,根据自己的需求也可以将心跳加快,当然服务端的负荷也会随之增加
  28. # heartbeat_interval = 10
  29. # heartbeat_timeout = 30
  30. # ssh is the proxy name same as server's configuration
  31. # 注意这里的项目名称[name],如果服务端是静态配置,客户端则需与之相符,否则就需要privilege_token,意为动态操作服务端配置
  32. [ssh]
  33. # tcp | http, default is tcp
  34. type = tcp
  35. local_ip = 127.0.0.1
  36. local_port = 22
  37. # true or false, if true, messages between frps and frpc will be encrypted, default is false
  38. # 加密项,如果开启了该功能,则在服务端也要做对应的配置
  39. use_encryption = false
  40. # default is false
  41. # 压缩
  42. use_gzip = false
  43. remote_port = 53001
  44. [dns]
  45. type = udp
  46. local_ip = 114.114.114.114
  47. local_port = 53
  48. # Resolve your domain names to [server_addr] so you can use http://web01.yourdomain.com to browse web01 and http://web02.yourdomain.com to browse web02, the domains are set in frps.ini
  49. [web01]
  50. type = http
  51. # 客户端於local service需要穿透的内网IP(局域网IP)
  52. local_ip = 127.0.0.1
  53. # 需要穿透的local service端口
  54. local_port = 80
  55. # 压缩
  56. use_gzip = true
  57. # connections will be established in advance, default value is zero
  58. # 连接池数量
  59. pool_count = 20
  60. # http username and password are safety certification for http protocol
  61. # if not set, you can access this custom_domains without certification
  62. # http连接的用户名口令,个人认为并没有什么卵用
  63. http_user = admin
  64. http_pwd = admin
  65. # if domain for frps is frps.com, then you can access [web01] proxy by URL http://test.frps.com
  66. # 从域名
  67. subdomain = test
  68. [web02]
  69. type = http
  70. local_ip = 127.0.0.1
  71. local_port = 8000
  72. [privilege_ssh]
  73. # if privilege_mode is enabled, this proxy will be created automatically
  74. privilege_mode = true
  75. type = tcp
  76. local_ip = 127.0.0.1
  77. local_port = 22
  78. use_encryption = true
  79. use_gzip = false
  80. # 注意该端口必须是外网服务已经开启了允许的范围值之端口
  81. remote_port = 6001
  82. [privilege_web]
  83. # 开启特权模式
  84. privilege_mode = true
  85. type = http
  86. local_ip = 127.0.0.1
  87. local_port = 80
  88. use_gzip = true
  89. # 自定义域名
  90. custom_domains = web03.yourdomain.com
  91. # locations is only useful for http type
  92. # 连接仅限http service路径
  93. locations = /,/pic
  94. # 重写header 域名host
  95. host_header_rewrite = example.com
  96. # 从域名
  97. subdomain = dev

穿透服务进程化启动 run on daemon

  1. import os, sys, time
  2. class bcolors:
  3. HEADER = '\033[95m'
  4. OKBLUE = '\033[94m'
  5. OKGREEN = '\033[92m'
  6. WARNING = '\033[93m'
  7. FAIL = '\033[91m'
  8. ENDC = '\033[0m'
  9. BOLD = '\033[1m'
  10. UNDERLINE = '\033[4m'
  11. def __init__(self):
  12. pass
  13. def fail(self,msg):
  14. print(self.FAIL+str(msg)+self.ENDC)
  15. def warn(self,params):
  16. print(self.WARNING+str(params)+self.ENDC)
  17. def info(self,msg):
  18. print(self.OKGREEN+str(msg) + self.ENDC)
  19. the_bcolors = bcolors()
  20. service_name = 'webdav_frpc'
  21. configfile = '/'+service_name+'.ini'
  22. class serviceStartDemo:
  23. def __init__(self):
  24. self.project_path = os.getcwd()
  25. self.service_name=service_name
  26. self.user = self.project_path.replace('/home/','').split('/')[0]
  27. self.pid_file = self.project_path+'/'+ self.service_name + '.pid'
  28. # self.runCommond = self.project_path+'/frpc -- -c '+ self.project_path+'/panetrate-mana-frpc.ini'
  29. self.runCommond = self.project_path+'/frpc -- -c '+ self.project_path+configfile
  30. def checkPidFile(self):
  31. return os.path.isfile(self.pid_file)
  32. def checkPortstatus(self):
  33. return self.getPid(self.service_port)
  34. def getPid(self,servciePort):
  35. #result = os.popen("lsof -i:"+str(servciePort)).readlines()
  36. #if (len(result) > 0):
  37. #resAry = result[1].split()
  38. #pidNum = resAry[1]
  39. #return pidNum
  40. #else:
  41. #return None
  42. with open(self.pid_file, 'r') as f:
  43. servicePid = f.readline()
  44. return servicePid
  45. def serverStart(self):
  46. if self.checkPidFile():
  47. the_bcolors.fail("pidfile is exist at "+str(self.pid_file)+" ,start failed!")
  48. return 0
  49. the_bcolors.info ("prepair to start "+self.service_name)
  50. os.chdir(self.project_path)
  51. fcmdStr="start-stop-daemon --start --quiet -b -v -m --pidfile=" + str(self.pid_file) + " --user " + str(self.user) + " -d "+self.project_path+" --exec " + str(self.runCommond) + " 2>/dev/null"
  52. os.system(fcmdStr)
  53. print(self.runCommond)
  54. checkCount = 0
  55. while checkCount < 10:
  56. if self.checkPidFile():
  57. the_bcolors.info("pidfile has been created!")
  58. break
  59. else:
  60. the_bcolors.warn ("pidfile still has not been created!")
  61. checkCount=checkCount+1
  62. time.sleep(6)
  63. if checkCount==10:
  64. the_bcolors.fail (self.service_name+" start failed")
  65. def serverStop(self):
  66. if self.checkPidFile():
  67. with open(self.pid_file, 'r') as f:
  68. servicePid = f.readline()
  69. if (servicePid is None) or (servicePid ==''):
  70. the_bcolors.info (self.service_name + " is already stoped!")
  71. else:
  72. os.system("kill -9 "+str(servicePid))
  73. the_bcolors.info (self.service_name + " is running with pid %s,prepro to kill it!"%(str(servicePid)))
  74. the_bcolors.info ("pidfile is exist at " + self.pid_file + " ,prepair to delete it!")
  75. os.system("rm -f " + self.pid_file)
  76. else:
  77. the_bcolors.warn ("pidfile is not exist!")
  78. return True
  79. def serverRestart(self):
  80. has_stop = self.serverStop()
  81. if(has_stop):
  82. self.serverStart()
  83. else:
  84. the_bcolors.fail("restart failed! plz try again")
  85. def serverStatus(self):
  86. runingStatus = 'false'
  87. if self.checkPidFile():
  88. pidfileStatus=self.pid_file
  89. else:
  90. pidfileStatus="not exists!"
  91. the_bcolors.info (""+self.service_name+" status:"+pidfileStatus)
  92. #the_bcolors.info (""+self.service_name+" status:")
  93. #the_bcolors.info ("running status: "+runingStatus)
  94. #the_bcolors.info ("running pid: "+ str(pid))
  95. #the_bcolors.info ("running pid file: "+pidfileStatus)
  96. pass;
  97. if __name__ == '__main__':
  98. try:
  99. operate = sys.argv[1]
  100. service = serviceStartDemo()
  101. if operate == "start":
  102. service.serverStart()
  103. elif operate == "stop":
  104. service.serverStop()
  105. elif operate == "restart":
  106. service.serverRestart()
  107. elif operate == "status":
  108. service.serverStatus()
  109. else:
  110. the_bcolors.fail ("param args only support start,stop,restart,status")
  111. except:
  112. the_bcolors.fail ("operate param must be required")

Ubuntu 16.04 以上的 systemd 脚本 使用 systemctl 进行服务维护操作
注意下列版本号为 0.21 版本,与上述不同

  1. #系统服务文件路径
  2. sudo vim /etc/systemd/system/frpc.service
  1. [Unit]
  2. Description=A frpc server
  3. #After=network.target
  4. Description=frpc daemon
  5. After=syslog.target network.target
  6. Wants=network.target
  7. [Service]
  8. Type=simple
  9. #注意这里的用户名,如果不存在,则先行创建
  10. User=nobody
  11. PIDFile=/var/run/frpc.pid
  12. #ExecStartPre=/usr/sbin/nginx -t -q -g 'daemon on; master_process on;'
  13. ExecStart=/home/jyo/tools/frp_0.21.0_linux_amd64/frpc -c /home/jyo/tools/frp_0.21.0_linux_amd64/tcp-util.ini
  14. ExecStop=/usr/bin/killall frpc
  15. TimeoutStopSec=5
  16. Restart=always
  17. RestartSec=20
  18. KillMode=mixed
  19. [Install]
  20. WantedBy=multi-user.target
  1. # 启动项目
  2. systemctl start frpc
  3. # 关闭项目
  4. systemctl stop frpc
  5. #将项目加入到系统字段启动
  6. systemctl enable frpc

技术文档

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注