frp概念
frp 是一个专注于内网穿透的高性能的反向代理应用,支持 TCP、UDP、HTTP、HTTPS 等多种协议。可以将内网服务以安全、便捷的方式通过具有公网 IP 节点的中转暴露到公网。
frp原理
1.frp 主要由 客户端(frpc) 和 服务端(frps) 组成,服务端通常部署在具有公网 IP 的机器上,客户端通常部署在需要穿透的内网服务所在的机器上。
2.内网服务由于没有公网 IP,不能被非局域网内的其他用户访问。
3.用户通过访问服务端的 frps,由 frp 负责根据请求的端口或其他信息将请求路由到对应的内网机器,从而实现通信。
frp特性
通过在具有公网 IP 的节点上部署 frp 服务端,可以轻松地将内网服务穿透到公网,同时提供诸多专业的功能特性,这包括:
- 客户端服务端通信支持 TCP、KCP 以及 Websocket 等多种协议。
- 采用 TCP 连接流式复用,在单个连接间承载更多请求,节省连接建立时间。
- 代理组间的负载均衡。
- 端口复用,多个服务通过同一个服务端端口暴露。
- 多个原生支持的客户端插件(静态文件查看,HTTP、SOCK5 代理等),便于独立使用 frp 客户端完成某些工作。
- 高度扩展性的服务端插件系统,方便结合自身需求进行功能扩展。
- 服务端和客户端 UI 页面。
frp 支持多种代理类型来适配不同的使用场景
类型 | 描述 |
---|---|
tcp | 单纯的 TCP 端口映射,服务端会根据不同的端口路由到不同的内网服务。 |
udp | 单纯的 UDP 端口映射,服务端会根据不同的端口路由到不同的内网服务。 |
http | 针对 HTTP 应用定制了一些额外的功能,例如修改 Host Header,增加鉴权。 |
https | 针对 HTTPS 应用定制了一些额外的功能。 |
stcp | 安全的 TCP 内网代理,需要在被访问者和访问者的机器上都部署 frpc,不需要在服务端暴露端口。 |
sudp | 安全的 UDP 内网代理,需要在被访问者和访问者的机器上都部署 frpc,不需要在服务端暴露端口。 |
xtcp | 点对点内网穿透代理,功能同 stcp,但是流量不需要经过服务器中转。 |
tcpmux | 支持服务端 TCP 端口的多路复用,通过同一个端口访问不同的内网服务。 |
frp docker镜像构建
# 1. docker-entrypoint.sh
cat >> docker-entrypoint.sh << EOF
#!/bin/sh
FRP_COMPONENT=$1
shift
FRP_HOME=${FRP_HOME:-/opt/frp}
if [ "$FRP_COMPONENT" = "frps" ]; then
$FRP_HOME/bin/frps -c $FRP_HOME/conf/frps.ini $@
elif [ "$FRP_COMPONENT" = "frpc" ]; then
$FRP_HOME/bin/frpc -c $FRP_HOME/conf/frpc.ini $@
else
$@
fi
EOF
# 2. Dockerfile
cat >> Dockerfile << EOF
FROM alpine:3.7
MAINTAINER darebeat
ENV SYS_ARCH=amd64 \
FRP_VER=0.34.1 \
FRP_HOME=/opt/frp \
PATH=$PATH:$FRP_HOME/bin
COPY docker-entrypoint.sh /
RUN apk --no-cache add wget tar tzdata \
&& cp -r -f /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
&& wget --no-check-certificate https://github.com/fatedier/frp/releases/download/v${FRP_VER}/frp_${FRP_VER}_linux_${SYS_ARCH}.tar.gz && tar zxvf frp_${FRP_VER}_linux_${SYS_ARCH}.tar.gz \
&& rm -rf frp_${FRP_VER}_linux_${SYS_ARCH}.tar.gz \
&& mkdir -p /opt/frp/conf \
&& mkdir -p /opt/frp/bin \
&& cp frp_${FRP_VER}_linux_${SYS_ARCH}/frps /opt/frp/bin \
&& cp frp_${FRP_VER}_linux_${SYS_ARCH}/frpc /opt/frp/bin \
&& cp frp_${FRP_VER}_linux_${SYS_ARCH}/frps.ini /opt/frp/conf \
&& cp frp_${FRP_VER}_linux_${SYS_ARCH}/frpc.ini /opt/frp/conf \
&& rm -rf frp_${FRP_VER}_linux_${SYS_ARCH} \
&& chmod +x /opt/frp/bin/frps \
&& chmod +x /opt/frp/bin/frpc \
&& apk del --purge wget tar
WORKDIR /opt/frp
ENTRYPOINT ["/docker-entrypoint.sh"]
CMD ["sh", "-c"]
在有外网IP的主机中部署frps
mkdir -p conf
cat >> conf/frps.ini << EOF [common] bind_port=17000 token=myToken vhost_http_port=10080 vhost_https_port=10443 dashboard_port=17500 dashboard_user=admin dashboard_pwd=admin tcp_mux=true max_pool_count=10 EOF cat>> docker-compose.yaml << EOF
version: "3"
services:
frp:
image: darebeat/frp:${FRP_VERSION:-0.34.1}
command: ${FRP_NODE:-frps}
container_name: ${FRP_NODE:-frps}
ports:
- "17000:17000"
- "17500:17500"
- "10022:10022" # ssh
- "13306:13306" # mysql
volumes:
- ./conf/${FRP_NODE:-frps}.ini:/opt/frp/conf/${FRP_NODE:-frps}.ini
EOF
docker-compose up -d
在需要穿透的内网主机上部署frpc
# 加入公网IP为 183.123.45.21
# 本机局域网IP为 192.168.23.99
mkdir -p conf
cat >> conf/frpc.ini << EOF [common] server_addr=183.123.45.21 server_port=17000 token=myToken [ssh] type=tcp local_ip=192.168.23.99 local_port=22 remote_port=10022 use_encryption=true use_compression=true [mysql] type=tcp local_ip=192.168.23.99 local_port=3306 remote_port=13306 EOF cat>> docker-compose.yaml << EOF
version: "3"
services:
frp:
image: darebeat/frp:${FRP_VERSION:-0.34.1}
command: ${FRP_NODE:-frpc}
container_name: ${FRP_NODE:-frpc}
network_mode: host
volumes:
- ./conf/${FRP_NODE:-frpc}.ini:/opt/frp/conf/${FRP_NODE:-frpc}.ini
EOF
docker-compose up -d
在别的机器上访问内网服务
ssh -p 10022 user@183.123.45.21 # ssh
http://183.123.45.21:17500 # dashboard
mysql -h 183.123.45.21 -P 13306 -u root -p # mysql