为 AutoSSH 端口转发配置 systemd 守护进程

SSH 端口转发是一个相当有用的技术,它既可以用于内网穿透,也可以用于明文数据的传输加密。出于稳定性的需要,我们一般希望在连接断开之后能够自动连接,而不是手动的重新开启一个链接。autossh 正是这样一个帮助我们自动重新建立连接的工具。本文将简单介绍 SSH 端口转发的三种类型,autossh 命令的书写以及其 systemd 守护进程配置文件的基本模板。

SSH 端口转发的三种类型

SSH 的端口转发可以分为三类,动态端口转发(Dynamic Forwarding, -D),本地端口转发(Local Forwarding, -L),远端端口转发(Remote Forwarding, -R)。

动态端口转发

动态端口转发的工作原理是,在你的本机打开一个 Socks 代理端口,任何发往这个端口的请求都会被转发到远端服务器。我们可以利用动态端口转发访问另一子网的网络资源。

比如说,你在子网A,子网B上架设了一个网站,不过处于安全策略的原因这个网站并没有对外暴露端口。在子网B上有一对外暴露 SSH 访问的跳板机,你可以通过 SSH 连接连接到跳板机上,然后通过动态端口转发将本地的请求发送到跳板机上,跳板机去请求子网B的资源再返回到你的电脑上。

再比如,你出于一个无法访问互联网(或某些网站)的子网内,然而在该网络内存在有一个可以访问互联网的设备,那么我们也可以利用动态端口转发来访问互联网(某些情况下我们可以通过连接本机和非计费主机翻过内网的计费网关)。

你可以这样建立连接:

1
ssh -D 1080 usernamme@example.com

本地端口转发

本地端口转发在做的事情是,在你的本机打开一个端口 A,这个端口和远端设备的端口 B 绑定,任何发往端口 A 的请求都会被转发到端口 B 上。实际的实现效果就像远端端口 B 上运行的服务被运行在了本机的端口 A 一样。

比如说,子网 B 中有一台未对外网暴露端口的 MySQL 服务器,但子网 B 中有一个对外暴露 SSH 服务的跳板机,我们希望在本机访问这个 MySQL 服务,那么就可以用本地端口转发达成这一需求。

你可以这样建立连接:

1
ssh -L localIp:localPort:remoteIp:remotePort usernamme@example.com

远端端口转发

远端端口转发和本地端口转发相反,在远端打开一个端口 A,这个端口 A 和本地的端口 B 绑定,在远端服务器访问端口 A 的时候,所有请求都会被发往本地的端口 B。实际运行的效果就像是本地端口 B 上运行的服务被运行在了远端端口 A 一样。

你可以这样建立连接:

1
ssh -R remoteIp:remotePort:localIp:localPort usernamme@example.com

autossh 命令的书写

在配置 autossh 之前,建议您配置无密码证书登录以确保后面的 systemd 守护进程能够正常运行,如果您不清楚如何配置,请参考此文

autossh 的命令比较直白一些,在 ssh 的命令前面加个 auto 再加几个参数基本上就能跑的起来了。举个例子:

autossh -M 0 -N -q -o “ServerAliveInterval 30” -o “ServerAliveCountMax 3” -L localIp:localPort:remoteIp:remotePort usernamme@example.com

这是一个建立本地端口转发的例子。

其中,ServerAliveInterval 30 的意思是,每三十秒戳一下远端服务器问它你还活着吗?ServerAliveCountMax 3 的意思是,如果戳三次它都不回复,那么就把这个连接拖到火葬场并且建立一个新的连接。

systemd 守护进程的基本配置

守护进程的模板长这个样子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[Unit]
Description=AutoSSH tunnel service
Wants=network-online.target
After=network.target network-online.target ssh.service

[Service]
Environment="AUTOSSH_GATETIME=0"
User=[REPLACE THIS TO YOUR USERNAME]
ExecStart=/usr/bin/autossh -M 0 -N -q -o "ServerAliveInterval 30" -o "ServerAliveCountMax 3" -L localIp:localPort:remoteIp:remotePort usernamme@example.com

ExecStop=/usr/bin/killall -s KILL autossh

[Install]
WantedBy=multi-user.target

它会在系统启动并且网络连通了、sshd服务也加载完了之后就启动 autossh服务。你需要把这个文件放在 /etc/systemd/system 内,文件名以 .service 结尾,比如 forward-mysql.service

接下来,刷新 systemd 守护进程列表:

1
sudo systemctl daemon-reload

启动你的服务:

1
sudo service [YOUR SERVICE FILE NAME] start

注意,替换方括号内的内容,不包含文件扩展名 .service

查看服务情况:

1
service [YOUR SERVICE FILE NAME] status

如果您看到了绿色的字,长得比较像这样:

Active: active (running) since Fri 2018-02-23 22:28:49 UTC; 7s ago

那么说明服务启动成功了,否则请重新检查配置。

最后,设置服务开机自动启动:

1
sudo systemctl enable [YOUR SERVICE FILE NAME]

以上就是本次介绍的全部内容,祝配置成功(*´ω`)人(´ω`*)。

推荐阅读

后记

其实我用这玩意翻学校的计费网关,在办公室开一台电脑 ssh 连过去白嫖流量上网,我们学校流量太贵了╰(〒皿〒)╯……