Linux奇淫技巧-systemctl和autossh实现ssh隧道代理和开机自启动

Linux奇淫技巧-systemctl和autossh实现ssh隧道代理和开机自启动

简述

自从ubuntu升级到18版本之后,貌似init和rc.local开机自启动脚本就不太好用了,于是开始放弃暴力简单的rc.local自启动,逐渐迁移到看起来更高大上的systemctl,systemd是一个系统管理守护进程、工具和库的集合,而systemctl就是systemd中的管理工具。想起来使用systemctl还是想把用authssh做ssh端口代理自启动,在用rc.local的过程中,遇到了不少苦难,所以转向使用systemctl,下面就先从配置autossh到使用systemctl配置autossh自启动。

autossh

ssh本身工具可以建立ssh隧道来代理端口,比如说代理22端口实现ssh反向代理实现内网穿透从外网ssh登录内网主机,当然也可以代理其他端口比如说80实现web服务的反向代理。autossh在ssh原有的功能上参与了端口监听,保证隧道的稳定性,原理不过多解释,可以搜到很多,这里重点说配置过程,本文以ubuntu 20.04系统为准,其他系统配置应该差不多。

安装autossh

ubuntu、debian用apt, centos用yum。

1
apt install autossh

开启端口访问

在远程代理主机上修改/etc/ssh/sshd_config下的GatewayPorts配置
、、、
GatewayPorts yes
、、、
开启sshd的任意IP绑定,不然只能从127.0.0.1上访问,使用service sshd start 重启sshd服务。

使用autossh

1
autossh -M 4010 -NR 4002:0.0.0.0:22 -i /root/.ssh/id_rsa -p 22 root@ip

-M 4010是指定用什么端口来实现监听保活,找个空闲的端口就行。
-NR 4002:0.0.0.0:22 这段参数的意思是将本地的22端口代理到远端4002端口上,0.0.0.0可以换成localhost就可以实现只能从远端主机本地访问内网主机22端口。
-i和-p就是普通ssh参数了,-i就是私钥地址,-p是远端主机ssh端口,推荐使用公私钥对登录ssh,不用每次都输入密码,这个在后面配置开机自启动也有帮助。
运行起来后,就可以通过ssh -p 4002 root@ip来穿透访问内网主机。

systemctl

systemd 概述

以前大多数开发者用的都是sysvinit来完成开机自启动工作,sysvinit看起来陌生,其实就是linux开发者经常用的rc.local和/etc/rc.d的这些启动脚本,通过定义level来决定启动顺序,并且必须得等这些脚本都启动完之后才允许用户登录。优点是简单,缺点也很明显,启动时间较长,而且是顺序执行,在多用户情况下,也会驱动全部服务,造成了浪费资源的情况。

在之后linux演进出了upstart,upstart没用过所以不讨论了,再之后就是systemd,ubuntu在18.04版本上将systemd用作默认启动管理器。相较于sysvinit,systemd可以并行执行启动服务,允许脚本在什么用户下启动,允许用户按需启动服务,尽可能减少了资源浪费,加快了用户登录过程。systemd中还有配置单元的概念,简化配置过程,增强服务能力。缺点也很明显,功能多带来多复杂性高了不少,这也是我时过两年才开始用起来systemd原因。

systemctl 用法

systemctl 有两种用法,一个是兼容之前多init下的service,一个是管理systemd下的unit资源,这里就只介绍更强大多unit资源的用法。
最好的学习方法就是实践,我们拿autossh开机自启动方式来开刀介绍简单的systemctl用法。

编写启动单元配置文件

ubuntu下systemd的启动单元文件在/lib/systemd/system/。在启动单元目录下,创建autossh.service文件。

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

[Service]
Type=simple
User=root
WorkingDirectory=/root
ExecStart=/usr/bin/autossh -M 4010 -NR 4002:localhost:22 -i /root/.ssh/id_rsa root@ip
Environment="AUTOSSH_GATETIME=2"

[Install]
WantedBy=multi-user.target

[Unit]

  • Description:定义了服务的描述,After定义了这个单元需要在network-online.target启动后再启动本服务,用空格作为分隔符,来导入多个服务。
  • Wants:表示此单元与network-online.target之间存在”弱依赖”关系,即如果network-online.target启动失败或停止运行,不影响该继续执行,同样也是用分隔符导入多个服务。
  • Requires:与Wants相反,如果其中的服务启动失败过着停止,该服务也需要停止。

[Service]

  • Type:定义了启动类型,它的设置值如下:

    • simple(默认值):ExecStart字段启动的进程为主进程
    • forking:ExecStart字段将以fork()方式启动,此时父进程将会退出,子进程将成为主进程
    • oneshot:类似于simple,但只执行一次,Systemd 会等它执行完,才启动其他服务
    • dbus:类似于simple,但会等待 D-Bus 信号后启动
    • notify:类似于simple,启动结束后会发出通知信号,然后 Systemd 再启动其他服务
    • idle:类似于simple,但是要等到其他任务都执行完,才会启动该服务。一种使用场合是为让该服务的输出,不与其他服务的输出相混合
      该段引用自阮一峰的网络日志
  • User:定义了使用该单元的用户。

  • WorkingDirectory:顾名思义,运行目录。

  • ExecStart:启动执行命令,与这个相关的有ExecReload、ExecStop、ExecStartPre、ExecStartPost、ExecStopPost,systemd的名字起的挺好,这几个大家按意思猜用途就行,顾名思义。

  • Environment:定义了环境变量。

[Install]

这里定义了服务的安装路径,实际上就是拷贝了该单元的配置文件到目标目录。

  • WantedBy:定义了该服务所在的服务组。
    这里划重点,multi-user.target是systemd的默认启动组,所有在这个组里的服务都将开机自启动,使用systemctl enable 服务名就可以开机自启动。所以这段install还真不能缺。

单元的使用方法

完成单元配置文件后使用下面命令:

1
2
3
4
5
6
systemctl enable autossh.service  // 启用开机自启
systemctl disable autossh.service // 关闭开机自启
systemctl start autossh.service // 启动服务
systemctl stop autossh.service // 停止服务
systemctl restart autossh.service // 重启服务
systemctl status autossh.service // 查看服务运行状态

下面是查看服务的运行状态

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
root@saber_nagato:~/# systemctl status autossh.service 
autossh.service - autossh
Loaded: loaded (/lib/systemd/system/autossh.service; enabled; vendor preset: enabled)
Active: active (running) since Tue 2020-12-15 01:56:04 UTC; 6 days ago
Main PID: 3832 (autossh)
Tasks: 2 (limit: 2205)
Memory: 2.6M
CGroup: /system.slice/autossh.service
├─ 3832 /usr/lib/autossh/autossh -M 4010 -NR 4002:localhost:22 -i /root/.ssh/id_rsa root@ip
└─210400 /usr/bin/ssh -L 4010:127.0.0.1:4010 -R 4010:127.0.0.1:4011 -NR 4002:localhost:22 -i /root/.ssh/id_rsa root@ip

Dec 19 06:22:04 nxp autossh[113831]: connect_to 127.0.0.1 port 4011: failed.
Dec 19 06:22:12 nxp autossh[113831]: connect_to 127.0.0.1 port 4011: failed.
Dec 19 06:26:45 nxp autossh[3832]: port down, restarting ssh
Dec 19 06:26:45 nxp autossh[3832]: starting ssh (count 6)
Dec 19 06:26:45 nxp autossh[3832]: ssh child pid is 201498
Dec 19 11:10:54 nxp autossh[201498]: connect_to 127.0.0.1 port 4011: failed.
Dec 19 11:10:54 nxp autossh[201498]: connect_to 127.0.0.1 port 4011: failed.
Dec 19 11:16:45 nxp autossh[3832]: port down, restarting ssh
Dec 19 11:16:45 nxp autossh[3832]: starting ssh (count 7)
Dec 19 11:16:45 nxp autossh[3832]: ssh child pid is 210400

结尾

以上基本完成了autossh和 systemctl配置开机自启动服务的过程,关于systemctl的细节配置可以去看阮一峰的网络日志仔细学习。