搭建 frp 内网穿透并启用 HTTPS 访问

frp 的搭建

项目地址: GitHub

frp 是一个可用于内网穿透的高性能的反向代理应用, 支持 tcp, udp, http, https 协议。

准备:

  • 客户端部署好支持 HTTPS 的 Web 服务

  • 防火墙开启所需端口

  • 服务器端绑定一个域名 (可选)

服务器端配置

自行选择平台, 以 64 位LInux为例下载 frp 的 Release 版 : GitHub

1
2
3
4
5
wget https://github.com/fatedier/frp/releases/download/v0.19.1/frp_0.19.1_linux_amd64.tar.gz

tar -xvf frp_0.19.1_linux_amd64.tar.gz

cd frp_0.19.1_linux_amd64

我们主要使用 frps, frps.ini 这两个文件, 客户端使用的 fprc, frpc.ini 可删除, 首先vim frps.ini进行配置

1
2
3
4
[common]
bind_port = 7000 # frp 服务所使用的端口
vhost_https_port = 443 # HTTPS 协议建议使用 443 端口
vhost_http_port = 80 # HTTP 协议建议使用 80 端口

保存后前台启动服务方便查看日志: sudo ./frps -c ./frps.ini

后台启动: sudo nohup ./frps -c ./frps.ini &

客户端配置

以树莓派为例, 应下载 64 位 ARM 版的 frp

1
2
3
4
5
wget https://github.com/fatedier/frp/releases/download/v0.19.1/frp_0.19.1_linux_arm.tar.gz

tar -xvf frp_0.19.1_linux_arm.tar.gz

cd frp_0.19.1_linux_arm

我们主要使用 frpc, frpc.ini 这两个文件, 服务器端使用的 fprs, frps.ini 可删除, 首先vim frpc.ini进行配置

1
2
3
4
5
6
7
8
9
10
11
12
13
[common]
server_addr = YOUR_SERVER_ADDR # 你的服务器 IP
server_port = 7000 # 对应 frp 服务器所用的端口

[https]
type = https # 配置 HTTPS 的转发
local_port = 443
custom_domains = YOUR_DOMAIN # 填写域名

[http]
type = http # 配置 HTTP 转发
local_port = 80
custom_domains = YOUR_DOMAIN # 填写域名

同样地, 前台启动: sudo ./frpc -c ./frpc.ini

没有错误就可以后台运行: sudo nohup ./frpc -c ./frpc.ini &

启用安全的 HTTPS 访问

准备:

  • 搭建好支持了 HTTPS 的 Web 服务

申请 SSL 证书

大部分主流的的浏览器都支持免费的 Let's Encrypt 证书, 在 SSL For Free 可以很方便地申请到, 首先输入你的域名

建议使用更加安全和方便的 Manual Verification

根据提示通过 FTP 或者 SFTP 将两个文件放在 http://yourdomain.com/.well-known/acme-challenge/下, 可以通过点击以上两个链接来验证是否成功, 再点击 Manually Verify Domain 等待网站验证域名所有权

验证成功后下载网站提供的 zip 包

配置 SSL 证书

为了避免部分浏览器出现 " 证书链长度为1 " 的不安全提示, 需要将 ca_bundle.crt 的内容复制到 certificate.crt 后面, 得到新的 certificate.crt

如果需要对得到的私钥进行加密, 使用如下命令:

1
openssl rsa -des3 -in private.key -out privatepass.key

最后, 将 privatepass.key 和 certificate.crt 添加到提供 HTTPS 访问的服务中, 就可以看到小绿锁啦

附上测试用代码

1
2
3
4
5
6
7
8
#!/usr/bin/python

import BaseHTTPServer, SimpleHTTPServer
import ssl

httpd = BaseHTTPServer.HTTPServer(('0.0.0.0', 443), SimpleHTTPServer.SimpleHTTPRequestHandler)
httpd.socket = ssl.wrap_socket (httpd.socket, certfile='/home/pi/webofthings.js/resources/certificate.crt',keyfile='/home/pi/webofthings.js/resources/private.key', server_side=True)
httpd.serve_forever()