网络拓扑·
flowchart LR
A("客户端<br/>私钥:id_ed25519_frp")
B("公网 Linux · frps<br/>TCP 6000:SSH 代理入口<br/>TCP 7000:FRP 隧道监听")
C("内网 Linux · frpc")
D("内网 sshd<br/>127.0.0.1:22")
A -->|"SSH 公钥认证<br/>PUBLIC_SERVER_IP:6000"| B
B -->|"通过 FRP 隧道转发 SSH 流量"| C
C -->|"TCP 127.0.0.1:22"| D
C -.->|"主动连接 frps:7000<br/>建立 TLS 加密隧道"| B
style A fill:#e0f2fe,stroke:#0284c7,color:#0c4a6e
style B fill:#fef3c7,stroke:#d97706,color:#78350f
style C fill:#dcfce7,stroke:#16a34a,color:#14532d
style D fill:#f3e8ff,stroke:#9333ea,color:#581c87
注:图中端口仅为示例,不建议使用默认端口。frp 是用于运行服务的受限 Linux 系统账户,不能用来 SSH 登陆
7000:frpc 到 frps 的连接端口,使用 FRP token 认证;
6000:访问公网 SSH 的代理端口;
22:内网机器 SSH 监听端口;
1 2 3 4 ❯ frps --version 0.71.1 ❯ frpc --version 0.71.1
部署流程·
提前生成 SSH 密钥对,私钥存在于本机,公钥安装在内网机器的 authorized_keys;
公网服务器·
公网服务器配置如下
1 2 3 4 5 6 7 OS: Ubuntu 24.04 noble Kernel: x86_64 Linux 6.8.0-117-generic Shell: zsh 5.9 Disk: 68G CPU: AMD EPYC 7K62 48-Core @ 2x 2.595GHz GPU: Cirrus Logic GD 5446 RAM: 3915MiB
执行下面指令安装和配置 frps
1 2 3 4 5 6 7 sudo apt update VERSION=0.71.1 ARCH=linux_amd64 curl -fL -o /tmp/frp.tar.gz "https://github.com/fatedier/frp/releases/download/v${VERSION}/frp_${VERSION}_${ARCH}.tar.gz" tar -xzf /tmp/frp.tar.gz -C /tmp sudo install -m 0755 "/tmp/frp_${VERSION}_${ARCH}/frps" /usr/local/bin/frps frps --version # 0.71.1
创建受限服务账户和配置目录,并生成专属 token
1 2 3 getent passwd frp >/dev/null || sudo useradd --system --user-group --no-create-home --shell /usr/sbin/nologin frp sudo install -d -m 0750 -o root -g frp /etc/frp openssl rand -hex 32 # 保留生成的 64 位 十六进制字符串到临时安全位置,避免泄露
修改配置文件 sudo vim /etc/frp/
1 2 3 4 5 6 7 8 9 10 11 12 13 bindAddr = "0.0.0.0" bindPort = 7000 allowPorts = [{ single = 6000 }] auth.method = "token" auth.token = "<FRP_TOKEN>" # 替换为刚才生成的 token auth.additionalScopes = ["HeartBeats", "NewWorkConns"] transport.tls.force = true log.to = "console" log.level = "info"
然后设置权限并校验
1 2 3 sudo chown root:frp /etc/frp/frps.toml sudo chmod 640 /etc/frp/frps.toml sudo /usr/local/bin/frps verify -c /etc/frp/frps.toml
创建 systemd 服务并启动 sudo vim /etc/systemd/system/frps.service
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 [Unit] Description =FRP ServerWants =network-on line.targetAfter =network-on line.target[Service] Type =simpleUser =frpGroup =frpExecStart =/usr/local/bin/frps -c /etc/frp/frps.tomlRestart =on -failureRestartSec =5 sNoNewPrivileges =true ProtectSystem =strictProtectHome =true PrivateTmp =true [Install] WantedBy =multi-user.target
配置服务启动
1 2 3 4 sudo systemctl daemon-reload sudo systemctl enable --now frps sudo systemctl status frps --no-pager sudo ss -lntp '( sport = :7000 )'
预期 frps 正常运行,TCP 7000 由 frps 监听。此时 TCP 6000 可能还未监听,需要等内网 frpc 注册代理之后才会出现。
下面配置防火墙与云安全
1 2 3 4 sudo ufw status verbose sudo ufw allow 7000/tcp sudo ufw allow from <EGRESS_IP> to any port 6000 proto tcp # 推荐外部 SSH 代理端口只运行可信固定 IP sudo ufw allow 6000/tcp # 若公网出口 IP 不固定,则执行此命令
内网机器·
内网机器安装 SSH 服务并且只启用公钥认证,安装并配置 frpc(与公网服务器安装步骤基本相同,但只安装 frpc)
1 2 3 4 5 6 VERSION=0.71.1 ARCH=linux_amd64 curl -fL -o /tmp/frp.tar.gz "https://github.com/fatedier/frp/releases/download/v${VERSION}/frp_${VERSION}_${ARCH}.tar.gz" tar -xzf /tmp/frp.tar.gz -C /tmp sudo install -m 0755 "/tmp/frp_${VERSION}_${ARCH}/frpc" /usr/local/bin/frps /usr/local/bin/frpc --version
创建受限账号与配置文件
1 2 3 4 getent passwd frp >/dev/null || sudo useradd --system --user-group \ --no-create-home --shell /usr/sbin/nologin frp sudo install -d -m 0750 -o root -g frp /etc/frp sudo vim /etc/frp/frpc.toml
写入配置文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 serverAddr = "<PUBLIC_SERVER_IP>" serverPort = 7000 auth.method = "token" auth.token = "<FRP_TOKEN>" auth.additionalScopes = ["HeartBeats" , "NewWorkConns" ]transport.protocol = "tcp" transport.tls.enable = true log.to = "console" log.level = "info" [[proxies]] name = "ssh" type = "tcp" localIP = "127.0.0.1" localPort = 22 remotePort = 6000
权限与校验
1 2 3 sudo chown root:frp /etc/frp/frpc.toml sudo chmod 640 /etc/frp/frpc.toml sudo /usr/local/bin/frpc verify -c /etc/frp/frpc.toml
创建 systemd 服务 sudo vim /etc/systemd/system/frpc.service
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 [Unit] Description =FRP Client ServiceWants =network-on line.targetAfter =network-on line.target[Service] Type =simpleUser =frpGroup =frpExecStart =/usr/local/bin/frpc -c /etc/frp/frpc.tomlRestart =on -failureRestartSec =5 sNoNewPrivileges =true ProtectSystem =strictProtectHome =true PrivateTmp =true [Install] WantedBy =multi-user.target
配置服务启动
1 2 3 4 5 6 7 sudo systemctl daemon-reload sudo systemctl enable --now frpc sudo systemctl status frpc --no-pager sudo journalctl -u frpc -n 30 --no-pager # login to server success # proxy added: [ssh] # [ssh] start proxy success
内网机器·
确认 sshd 服务
1 2 3 4 5 6 sudo ss -lntp '( sport = :22 )' timeout 5 bash -c 'exec 3<>/dev/tcp/127.0.0.1/22; IFS= read -r line <&3; printf "%s\n" "$line"' # State Recv-Q Send-Q Local Address: Port Peer Address: Port # LISTEN 0 128 0.0.0.0:22 0.0.0.0:* users :(("sshd", pid = 338 , fd = 6 )) # LISTEN 0 128 [::]:22 [::]:* users :(("sshd",pid=338 ,fd=7 )) # SSH-2.0-OpenSSH_10.4p1 Debian-5
公网服务器·
确认 frps 服务(在 frpc 注册之后出现对 6000 端口的监听)
1 2 3 4 sudo ss -lntp '( sport = :7000 or sport = :6000 )' # State Recv-Q Send-Q Local Address: Port Peer Address: Port Process # LISTEN 0 4096 *: 7000 *:* users :(("frps", pid = 988511 , fd = 4 )) # LISTEN 0 4096 *: 6000 *:* users :(("frps", pid = 988511 , fd = 8 ))
验证 FRP 转发到 SSH
1 2 3 4 5 6 timeout 10 bash -c ' exec 3<>/dev/tcp/127.0.0.1/6000 IFS= read -r line <&3 printf "%s\n" "$line" ' # SSH-2.0-OpenSSH_10.4p1 Debian-5
配置完成后,使用本机尝试 SSH 登录内网机器 sh -p 6000 <username>@<remote_ip>
参考资料·
frp | 配置文件
常用实时日志
1 2 3 4 5 # 公网服务器 sudo journalctl -u frps -f # 内网机器 sudo journalctl -u frpc -f sudo journalctl -u ssh -f
多台内网机器独立配置 frpc 可共用一个 frps:7000,但是代理名称和公网端口不能冲突,形如
内网机器
name
localPort
remotePort
Windows 连接
A
ssh-machine-a
2200
6000
ssh -p 6000 userA@<PUBLIC_SERVER_IP>
B
ssh-machine-b
2201
6001
ssh -p 6001 userB@<PUBLIC_SERVER_IP>
C
ssh-machine-c
2202
6002
ssh -p 6002 userC@<PUBLIC_SERVER_IP>
并且增加其它机器后,需要同步修改 frps.toml 文件 allowPorts = [{ start = 6000, end = 6002 }],更新防火墙策略。
讨论
评论