赞
踩
在公网服务器搭建frps(service),在内网本地机子搭建frpc(client),流量通过访问公网ip,经过frps服务端转发到fprc客户端,fprc再转发到本地web应用。
官方下载地址 https://github.com/fatedier/frp/releases
官方文档地址https://gofrp.org/docs/
服务端:frp_0.44.0_linux_amd64.tar.gz
客户端:frp_0.44.0_windows_amd64.zip
这里我用虚拟机模拟了一台公网服务器:192.168.111.201
- # 解压
- tar -xzvf frp_0.44.0_linux_amd64.tar.gz
- cd frp_0.44.0_linux_amd64
- # 配置服务端
- vi frps.ini
配置 frps.ini
- [common]
- # frp服务端的端口,frp客户端需要连接这个端口握手
- bind_port = 7000
- # 公网服务端对外提供的http端口
- vhost_http_port=8080
启动服务端
./frps -c frps.ini
后台启动运行服务端
nohup ./frps -c frps.ini >/dev/null 2>&1 &
配置 frpc.ini
- [common]
- # frps服务端的ip和端口
- server_addr = 192.168.111.201
- server_port = 7000
-
- [web01]
- type = http
- # 本地web应用的ip和端口
- local_ip = 127.0.0.1
- local_port = 8080
- #公网服务器的ip或域名
- custom_domains = 192.168.111.201
到解压根目录启动客户端
frpc -c frpc.ini
访问公网ip已经可以反向代理到本地web服务了。
以上就是一个简单的内网穿透 http 例子。
使用官方推荐的如下配置:
frps.ini
- [common]
- bind_port = 7000
- vhost_https_port = 443
frpc.ini
- [common]
- server_addr = 192.168.111.201
- server_port = 7000
-
- [plugin_https2https]
- type = https
- custom_domains = 192.168.111.201
- plugin = https2https
- plugin_local_addr = 127.0.0.1:8443
- #plugin_crt_path = ./server.crt
- #plugin_key_path = ./server.key
- plugin_host_header_rewrite = 127.0.0.1
- plugin_header_X-From-Where = frp
结果一直报如下错误,没找到解决办。
研究了好久,才反应过来,http协议在应用层,tcp在传输层,且http是基于tcp的。
既然https失败了,直接转发tcp就是,把ssl放在本地web应用中就可以了,frp只做tcp流量转发。
frps.ini
- [common]
- bind_port = 7000
frpc.ini
- [common]
- server_addr = 192.168.111.201
- server_port = 7000
-
- [tcp]
- type = tcp
- # 本地web应用的ip和端口
- local_ip = 127.0.0.1
- local_port = 8443
- # 公网服务器提供给外网访问的端口
- remote_port = 443
上面有2个不安全的地方:
1、frpc 和 frps 之间的身份验证不安全,默认为 token,这种方式存在被中间人攻击的威胁。
2、frpc 和 frps 之间的流量未加密,可以通过 TLS 协议加密,解决被中间人攻击的威胁。
frps.ini
- [common]
- #frps服务端监听的端口,frpc客户端要来连接。
- bind_port = 7000
- #密码设置复杂点,frps服务端密码和frpc客户端密码要一致。
- token = mm123456789
frpc.ini
- [common]
- # frps服务端的ip和端口
- server_addr = 192.168.111.201
- server_port = 7000
- #密码设置复杂点,frps服务端密码和frpc客户端密码要一致。
- token = mm123456789
-
- [tcp]
- type = tcp
- # 本地web应用的ip和端口
- local_ip = 127.0.0.1
- local_port = 8443
- # 公网服务器提供给外网访问的端口
- remote_port = 443
双向验证即 frpc 和 frps 通过本地 ca 证书去验证对方的身份。理论上 frpc 和 frps 的 ca 证书可以不同,只要能验证对方身份即可。
frps.ini
- # frps.ini
- [common]
- #frps服务端监听的端口,frpc客户端要来连接。
- bind_port = 7000
- #密码设置复杂点,frps服务端密码和frpc客户端密码要一致。
- token = mm123456789
-
- tls_cert_file = ./server.crt
- tls_key_file = ./server.key
- tls_trusted_ca_file = ./ca.crt
frpc.ini
- # frpc.ini
- [common]
- # frps服务端的ip和端口
- server_addr = 192.168.111.201
- server_port = 7000
- #密码设置复杂点,frps服务端密码和frpc客户端密码要一致。
- token = mm123456789
-
- # frpc开启TLS加密功能
- tls_enable = true
- tls_cert_file = ./client.crt
- tls_key_file = ./client.key
- tls_trusted_ca_file = ./ca.crt
-
- [tcp]
- type = tcp
- # 本地web应用的ip和端口
- local_ip = 127.0.0.1
- local_port = 8443
- # 公网服务器提供给外网访问的端口
- remote_port = 443
-

- cat > my-openssl.cnf << EOF
- [ ca ]
- default_ca = CA_default
- [ CA_default ]
- x509_extensions = usr_cert
- [ req ]
- default_bits = 2048
- default_md = sha256
- default_keyfile = privkey.pem
- distinguished_name = req_distinguished_name
- attributes = req_attributes
- x509_extensions = v3_ca
- string_mask = utf8only
- [ req_distinguished_name ]
- [ req_attributes ]
- [ usr_cert ]
- basicConstraints = CA:FALSE
- nsComment = "OpenSSL Generated Certificate"
- subjectKeyIdentifier = hash
- authorityKeyIdentifier = keyid,issuer
- [ v3_ca ]
- subjectKeyIdentifier = hash
- authorityKeyIdentifier = keyid:always,issuer
- basicConstraints = CA:true
- EOF

- openssl genrsa -out ca.key 2048
- openssl req -x509 -new -nodes -key ca.key -subj "/CN=example.ca.com" -days 3650 -out ca.crt
将 192.168.111.201 改成自己的服务端的ip
- openssl genrsa -out server.key 2048
-
- openssl req -new -sha256 -key server.key \
- -subj "/C=XX/ST=DEFAULT/L=DEFAULT/O=DEFAULT/CN=192.168.111.201" \
- -reqexts SAN \
- -config <(cat my-openssl.cnf <(printf "\n[SAN]\nsubjectAltName=DNS:localhost,IP:127.0.0.1,DNS:server.com,IP:192.168.111.201")) \
- -out server.csr
-
- openssl x509 -req -days 3650 -sha256 \
- -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial \
- -extfile <(printf "subjectAltName=DNS:localhost,IP:127.0.0.1,DNS:server.com,IP:192.168.111.201") \
- -out server.crt
使用 who 命令查询客户端的ip地址。我这里是192.168.111.1
将 192.168.111.1 改成自己的客户端的ip
- openssl genrsa -out client.key 2048
- openssl req -new -sha256 -key client.key \
- -subj "/C=XX/ST=DEFAULT/L=DEFAULT/O=DEFAULT/CN=192.168.111.1" \
- -reqexts SAN \
- -config <(cat my-openssl.cnf <(printf "\n[SAN]\nsubjectAltName=DNS:client.com,IP:192.168.111.1")) \
- -out client.csr
-
- openssl x509 -req -days 3650 -sha256 \
- -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial \
- -extfile <(printf "subjectAltName=DNS:client.com,IP:192.168.111.1") \
- -out client.crt
最终生成了10个文件。
server.crt、server.key、ca.crt 拷贝到 frp服务端解压目录下。
client.crt、client.key、ca.crt 拷贝到 frp客户端解压目录下。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。