基于樱花frp内网穿透的三点式远程连接内网服务器

问题描述

现在有 电脑C1 和 电脑C2(均接入公网,但 电脑C1 与 电脑C2 之间无法直接ping通),而 电脑C2(midUser@10.108.1.1)可以通过 SSH 等服务连接其内网的 目标服务器T(targetUser@10.108.1.2)。现要求使用 电脑C1(mainUser@192.168.1.1)可以同样通过 SSH 等服务连接到目标服务器 T(以 电脑C2 的网络环境为媒介),并且无需对 目标服务器T 有任何操作,但要求有可以长期存在或可远控启动的 副机C2。

隧道设计

实现原理

主机C1 通过 云服务器S 连接 副机C2(与 目标服务器T 同处一个内网),按端口转发规则实现在 主机C1 连接到 目标服务器T 的 SSH 服务。

网络传输图
远程连接内网服务器

实际操作

前提

以 SSH 服务的连接需求为例:

  • 主机 C1:可连接公网,开启了 OpenSSH 服务。

  • 副机 C2:可连接公网,开启了 OpenSSH 服务;并且与 T 共处一个内网(可以相互连接)。

  • 云服务器 S:可以连接任意主副机 C1 和 C2,注意依照如流量、网速和使用需求等方面选择服务端。

  • 目标服务器 T:开启了 OpenSSH 服务,与副机 C2 共处一个内网(可以相互连接)。

步骤1:配置与开启云服务器

一般是获取性能较好(网速等)的通用型云服务器,还会涉及域名的购买与获取(该云服务器的公网IP),然后先在云服务器上配置内网穿透服务端 frps,再于副机配置内网穿透客户端 frpc,具体可查看网上教程(frp为开源项目,关键词——frp实现内网穿透)。

这里以 樱花穿透(Sakura FRP) 作为内网穿透的手段,且其自带轻量级云服务器(无需配置 域名 和 frps),则没有太多要求。

注册账户

主页获取访问密钥 3w51234567890123

每日登录可以领取若干 GB 的流量,也可以充值会员追求更高网络性能

创建隧道

一般无需在意地区选择,至于副机所处网络的具体运营商可以查询,尽量选择通用穿透节点。

但需注意:

  • 对于 广东省内非联通网络 的用户,使用 任何联通节点 可能存在问题
  • 对于 其他非联通网络 的用户,使用 广东联通 节点可能存在问题
  • 对于 广东联通网络 的用户,使用 除广东联通外的任何联通节点 可能存在问题

即联通用户尽量选择省内联通节点。

但是,本人的深圳副机用不了广州或深圳节点,似乎只能使用济南联通的任意节点(一个坑,反正大部分其他节点都用不了)

注意配置完成后,进行节点迁移会导致隧道IP地址变更,所有针对原节点地址的授权状态也会被消除。因此,除非万不得已,不要改变已有节点。

查询副机的网络运营商(以 Linux 64 系统为例):

curl ipinfo.io
# 所得 org 字号的值为运营商标签,如 China Unicom 为中国联通

注意:需要自己试错出个人实际可用的节点,有些节点可能被副机所在内网屏蔽。

配置隧道

选用 TCP 隧道,并生成访问密码(一般不会用到得到的明码,且要避免显式记录在任何地方)。

创建并配置后,在所得隧道的 操作 - 配置文件 中获得服务端的运行参数 -f 3w51234567890123:19220000

注意:本地端口可自行编写要转发到的端口,一般按需求不与被转发端口相同(我这里定义的 2222 端口在副机中未曾被占用)

授权访问

主机登录樱花穿透管理界面,点击刚创建隧道的 三点菜单 - 授权访问 - 选择“使用本机IP” 可以快捷授权主机对该隧道的访问权限。

若有多个主机或下级主机不便登录管理界面,可以填入其 IPv4 地址授权即可(亦有一键认证等其他方式,具体见樱花穿透帮助文档)。

手动授权访问

一键认证(无需登录FRP管理员后台,在主机每次运行可执行程序自动进行认证,该程序由上级用户或管理员派发)

根据主机系统架构选取对应的认证工具(只对单个隧道的指定系统架构有效)

下载得到 .exe 认证程序,每次需要认证的时候自行运行该认证程序即可。

注意:如果同一隧道发生节点迁移或者隧道重启,一般都需要重新认证(一键认证也一样)。

步骤2:副机配置

如果无法直接操作副机,可以使用 raylink 等未被内网屏蔽的远控软件在主机远程控制副机进行配置。

副机可以承载多个隧道,转发源自多个目标服务器的端口。

端口转发

副机(以midUser用户为例)的终端中输入:

ssh -L 2222:10.108.1.2:22 midUser@localhost

这样可以将目标服务器(以 10.108.1.2 为例)的 SSH 服务端口 22 映射到副机自定义的本地转发端口 2222 上,使得连接 midUser@localhost:2222 与连接 targetUser@10.108.1.2:22 等效。

进行端口转发的原因:首先防止与副机自身的 SSH 端口 .22 冲突,因为本意并非开放副机的 SSH 服务端口,而是转发目标服务器的 SSH 服务端口。其次是我的副机所处内网还禁止 .22 端口对公网的直接开放(裸开)。

注意:命令窗口关闭或副机重启时会导致最近一次端口转发操作失效,故需要为此独立地配置自启服务项!

状态检验

在副机终端输入:

sudo netstat -tuln | grep 2222

# 若配置有多个
sudo netstat -tuln | grep -E '2222|2223'

可以查看端口转发情况(是否处于监听状态):

内网穿透配置

以樱花穿透FRP为例,在 https://www.natfrp.com/tunnel/download 中获取对应副机系统架构的内网穿透工具的下载地址(以 frpc 为例)。

以 Linux 64 位 为例:

cd /usr/local/bin

# 一般来说只需要使用这条命令:
wget -O frpc <下载地址>

# 如果上面的命令报错,请尝试这条:
curl -Lo frpc <下载地址>

# 添加权限
chmod 755 frpc

# 查看权限状态
ls -ls frpc

# 查询文件完整性
md5sum frpc

# Linux frpc 通常已经过 UPX 压缩,如需下载未压缩的版本请在下载地址尾部加上 _noupx
# 更具体下载和安装方式查看使用帮助。

下载完后可以在任意目录下的终端输入 frpc -v 检验是否安装成功(是否配置到全局上)。

激活隧道

查看隧道配置文件参数,然后以此激活隧道(格式为 -f [个人访问密钥]:[隧道ID [, 隧道ID2, ...]],以逗号分隔可以批量同时开启隧道,命令窗口关闭时也会一起关闭):

frpc -f 3w51234567890123:19220000

获得公网地址与开放端口 60.215.128.117:11500

显然,在主机中 ping 公网IP 60.215.128.117 一定是连通的,也可以在主机终端中测试是否能正常连接 SSH 服务:

ssh -p 11500 targetUser@60.215.128.117
# ssh -p [云服务器开放端口] 目标服务器用户名@云服务器IP

配置自启

先在副机(以 Linux 64 为例)查询 初始化系统 的类型

if [[ `/sbin/init --version` =~ upstart ]]; then echo Upstart; elif [[ `systemctl` =~ -\.mount ]]; then echo systemd; elif [[ -f /etc/init.d/cron && ! -h /etc/init.d/cron ]]; then echo SysVinit; else echo Unknown; fi

systemd 为例,参考文档 frpc 配置自启

注意:绝对不可以重复开启同一隧道服务,如一边是通过系统服务启动,一边是手动指令 frpc -f 启动,会出现不可预计的问题。

配置步骤

创建服务目录
sudo mkdir -p /usr/local/etc/natfrp
编辑服务项1(frpc自启)
sudo vi /etc/systemd/system/frpc@.service
[Unit]
Description=SakuraFrp Service
After=network.target

[Service]
Type=idle
#DynamicUser=yes
Restart=on-failure
RestartSec=60s
ExecStart=/usr/local/bin/frpc -f %i
WorkingDirectory=/usr/local/etc/natfrp

[Install]
WantedBy=multi-user.target

同系统通用,直接复制即可。

编辑服务项2(端口转发自启)
sudo vi /etc/systemd/system/ssh-tunnel.service
[Unit]
Description=SSH Tunnel for Port Forwarding
After=network.target

[Service]
Type=oneshot
Environment=HOME=/home/midUser
ExecStart=/usr/bin/ssh -i /home/midUser/.ssh/id_rsa -L 2222:10.108.1.2:22 midUser@localhost -N -f
ExecStart=/usr/bin/ssh -i /home/midUser/.ssh/id_rsa -L 2223:以此类推:22 midUser@localhost -N -f
RemainAfterExit=yes
Restart=on-failure
RestartSec=15
User=midUser
NoNewPrivileges=no
ProtectHome=no
ProtectSystem=no

[Install]
WantedBy=multi-user.target

注意

  • 其中的 User= 填入自己的副机用户名,ExecStart= 则填入自己的具体端口转发指令(注意 SSH 指令不支持密码明码输入,在服务项中只能通过配置密钥文件来验证),Environment= 填入自己的用户根目录防止识别不到用户环境。
  • 其中重点是 Type=oneshot可以有多句 ExecStart= 对应多个隧道配置,否则哪怕服务正常执行也不会出现监听效果且导致无法支持多个 ExecStart 存在。
SSH密钥获取与配置

生成 SSH 密钥(副机本地的 ~/.ssh/id_rsa

所有提示输入直接回车跳过即可。

ssh-keygen -t rsa -b 4096

将公钥复制到副机本地(副机本地的 ~/.ssh/id_rsa.pub

请注意,端口转发指令的目标就是副机自己,不要错认为是目标服务器 T。这里需要密钥配置只是因为执行这条命令需要副机自己的管理员用户验证,所以公钥也直接存在自己这里,保证每次执行 SSH 相关指令的时候都不用重新输入管理员账户的密码。

ssh-copy-id midUser@localhost

确保 SSH 配置文件可访问

chmod 600 /home/midUser/.ssh/id_rsa
chmod 700 /home/midUser/.ssh
chmod 644 /home/midUser/.ssh/authorized_keys

测试直连(成功后 exit 退出即可,退出后当前窗口才是之前的状态,不然是翻不到以前所输入的指令记录的)

ssh midUser@localhost
重载 systemd

前述步骤任意修改都需要经历重载。

systemctl daemon-reload
启用服务

启用后即可自启,注意至少有两个服务项需要自启。

systemctl <enable|disable> <Unit名称>

常用指令

启停服务

隧道服务的Unit名称格式为 frpc@访问密钥:隧道ID[, 隧道ID2, ...]

systemctl <start|stop> <Unit名称>

# 例如:
systemctl start frpc@3w51234567890123:19220000	

查看服务状态

systemctl status <Unit名称>

# 例如:
sudo systemctl status frpc@3w51234567890123:19220000
sudo systemctl status ssh-tunnel.service # 若没有在 status 中显示 SUCCESS 则需要修复在前面的步骤

查看所有当前运行中的隧道的情况--all参数可以列出包含停止的服务)

systemctl list-units [--all] "frpc@*"


(此图源自樱花穿透帮助文档)

查看服务日志

journalctl -u <Unit名称>

如果当前窗口无法显示所有日志,可以用 ↑、↓ 方向键滚动,输入大写的 G 跳转动到日志底部,输入 q 退出日志查看(对 systemctl status 的输出信息同样适用)。更多使用方法请参阅 man journalctl

步骤3:主机配置

原本目标服务器 T 的连接配置为 targetUser@10.108.1.2:22,平替为 targetUser@60.215.128.117:11500 即可。

目标服务器用户名@目标服务器IP:服务端口  -->  目标服务器用户名@云服务器IP:云服务器开放端口

副机每次重启或单独重启隧道服务时,都需要进行认证,或者一键运行认证可执行程序(如 auth-guest_windows_amd64-19220000.exe之类的,一个隧道对应一种操作系统的一个认证程序,除非隧道参数有改动,否则都是这同一个认证),或者人工在管理员后台验证。

本次案例中在每次重启服务时需要运行 auth-guest_windows_amd64-19220000.exeauth-guest_windows_amd64-19220001.exe 分别代表两个隧道认证。

对于每次需要多个隧道认证的用户,可以采用以下方案:

在主机(使用者)创建如下目录,将所有 .exe 认证程序置于 \authorization 文件夹中,只需要运行 run.bat 即可一次性全部认证。

run.bat

@echo off
REM 设置代码页为 UTF-8
chcp 65001 >nul

REM 获取当前脚本所在的目录
set "SCRIPT_DIR=%~dp0"

REM 设置目标文件夹路径
set "TARGET_DIR=%SCRIPT_DIR%authorization"

REM 检查目标文件夹是否存在
if not exist "%TARGET_DIR%" (
    echo 错误:文件夹 "%TARGET_DIR%" 不存在!
    pause
    exit /b 1
)

REM 遍历目标文件夹中的所有 .exe 文件
for %%f in ("%TARGET_DIR%\*.exe") do (
    echo 正在运行: %%f
    start "" "%%f"
    REM 等待当前程序运行完成
    call :waitForProcess "%%f"
)

echo 所有 .exe 认证程序已运行完毕!请勿重复运行,否则会各自报错但不影响。
pause
exit /b 0

REM 等待进程完成的函数
:waitForProcess
set "EXE_PATH=%~1"
set "EXE_NAME=%~nx1"
:checkProcess
tasklist /FI "IMAGENAME eq %EXE_NAME%" 2>nul | find /I "%EXE_NAME%" >nul
if %ERRORLEVEL%==0 (
    timeout /T 1 /NOBREAK >nul
    goto checkProcess
)
goto :eof
posted @ 2025-01-17 15:45  #Dragon  阅读(1174)  评论(0)    收藏  举报