侧边栏壁纸
博主头像
ldwcool's Blog博主等级

行动起来,活在当下

  • 累计撰写 24 篇文章
  • 累计创建 10 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

SSH 使用小全

ldwcool
2023-07-27 / 0 评论 / 2 点赞 / 191 阅读 / 16421 字

安装

安装命令:

sudo apt install openssh-server

查看服务的状态:

systemctl status sshd.service

配置

包括服务端和客户端配置

服务端常用配置

编辑ssh服务配置文件

sudo vim /etc/ssh/sshd_config

常用配置如下:

Banner /etc/issue.net        # 登录前提示信息
Port 22                      # 工作端口
PubkeyAuthentication yes     # 允许公钥登录,ssh 除了可以用账号密码登录外还可以用公私钥来进行登录
ListenAddress 12.34.56.78    # 侦听地址,比如服务器有两块网卡,现在只能让用户通过第一块网卡来进行 ssh 连接,那么后面的地址就写第一块网卡的 IP 地址
PermitRootLogin no           # 是否允许 root 账号来通过 SSH 登录;no 表示完全禁用;prohibit-password 表示禁止通过账号密码登录,但是可以通过公钥的方式登录
Protocol 2                   # 只允许 SSH 2 协议来连接
AllowUsers user1 user2       # 只允许 user1 和 user2 账号通过 SSH 连接
DenyUsers user3              # 禁止 user3 账号通过 SSH 连接
AllowGroups sshusers         # 只允许 sshusers 组里面的账号可以通过 SSH 连接
PasswordAuthentication no    # 禁止使用密码登录

其它 SSH 配置详解

解决连接自动断开问题

问题描述:ssh 连接长时间不操作自动断开

解决方法共有三种

  • 修改服务器端参数
# 如果你用多台本地机器连接服务器,可以考虑把服务器端的配置做修改(路径是:/etc/ssh/sshd_config),在其中添加一行内容
ClientAliveInterval  60  # 意思是每 60 秒向客户端发一次保持连接的信号

# 如果仍要设置断开时间,还有一个参数可以添加
ClientAliveCountMax  60  # 意思是如果客户端 60 次未响应就断开连接,依据你期望的时间来设定
  • 修改本地参数
# 也可以让客户端向服务器发送保持连接的信号(路径是/etc/ssh/ssh_config)

# 在其中类似的添加相应的参数也行
ServerAliveInterval  60
ServerAliveCountMax  60
  • 连接时指定参数
# 在连接前使用 -o 设置相应的参数
ssh -o ServerAliveInterval=30 root@192.168.1.1

SSH 工具

openssh 是一个服务套件,安装openssh-server时不仅会安装 ssh 的服务端程序,还会安装一大堆 ssh 相关工具,比如:sftpscp

SCP 工具

相当于将 ssh 和 rcp 结合,rcp 是明文传输的,通过 ssh 为通信双方建立一个安全加密的隧道,然后将 rcp 数据通过这个隧道传输以此实现数据的加密传输。

  • 拷贝一个文件到目标机器上
scp a.txt 192.168.2.207:

默认使用本地账号名登录远程系统,并且默认拷贝到这个账号的主目录下

注意:最后面的冒号不能省

  • 指定用户名、目标路径拷贝文件到远程机器上
scp a.txt study@192.168.2.207:/tmp/b.txt

将本机的 a.txt 通过 192.168.2.207 机器上的 study 账号拷贝到 /tmp/b.txt 路径下

  • 拷贝一个目录到远程机器上
scp -rv dir/ study@192.168.2.207: 

将本机的 dir/ 目录通过 192.168.2.207 机器上的 study 账号拷贝到其主目录下

参数:r: 递归拷贝 v:显示进度

  • 拷贝远程机器文件到本机
scp study@192.168.2.207:/tmp/b.txt .

通过 192.168.2.207 机器上的 study 账号将 /tmp/b.txt 到本机当前目录下

SFTP 工具

相当于将 ssh 和 ftp 结合,ftp 是明文传输的,通过 ssh 为通信双方建立一个安全加密的隧道,然后将 ftp 数据通过这个隧道传输以此实现数据的加密传输。

  • 连接 sftp
sftp study@192.168.2.207

连接成功后就会得到一个类似 ftp 的命令提示符,所有适用于 ftp 的指令在 sftp 命令提示符中都可以使用。

sftp> help、ls、cd、get(下载)、wget、put(上传)、mput、quit

客户端连接

有三种连接方式:分别是指定用户名密码,配置文件和使用公钥进行登录。

通过用户名密码

ssh study@192.168.2.207

ssh -l study 192.168.2.207

通过配置文件

首先编辑配置文件:~/.ssh/config

host fileserver               # 这一组的名称,随意
  Hostname 192.168.2.207
  Port 22
  User zhangsan
Host mailserver               # 这一组的名称,随意
  Hostname mail.lab.com
  Port 2222
  User lisi

编辑完成之后,保存。

之后就可以使用ssh fileserver这条命令连接 192.168.2.207:22 机器上的 zhangsan 账号,省去了输入 IP、端口、账号等信息

通过公钥

什么是公钥 / 私钥?

非对称算法(公钥算法),通过一次数学运算会生成两个值,一个是公钥,一个是私钥,无所谓哪个是公钥哪个是私钥,因为用公钥加密的只能用对应的私钥解密,用私钥加密只能用对应的公钥解密。

注意:公钥是拿出去给别人用,私钥得自己严格保密。

通过公钥登录的步骤:

  1. 生成密钥对(如果已有可跳过)

    • 使用 rsa 非对称加密算法,并指定密钥长度为 4096。
    ssh-keygen -t rsa -b 4096
    

    生成的私钥位置在:~/.ssh/id_rsa;公钥位置在:~/.ssh/id_rsa.pub

    • 命名密钥对,生成密钥对 id_mail 用来登录邮件服务器,生成密钥对 id_ftp 用来登录 ftp 服务器等。
    ssh-keygen -t rsa -b 4096 -f id_mail
    
    ssh-keygen -t rsa -b 4096 -f id_ftp
    
    • 修改私钥密码,可以设置为空(不建议)
    ssh-keygen -p -f ~/.ssh/id_rsa
    

    参数:p表示修改密码;f指定修改的目标

  2. 上传公钥到目标机器

    • 拷贝公钥到目标机器上(本机只有一个公钥时)

      ssh-copy-id study@192.168.2.207
      
    • 拷贝指定的公钥到目标机器上

      ssh-copy-id -i id_rsa.pub study@192.168.2.207
      

    拷贝后目标机器会生成~/.ssh/authprized_keys文件,内容上传的公钥内容相同。

    上传完公钥后,再次用 ssh 连接时就不需要输入账号密码了,输入的密码是私钥的密码,如果把私钥的密码设置为空那么就可以直接连接了,什么密码都不用输入(当然不建议这么做)。

SSH 其他应用

ssh 除了能远程登录之外,还有很多非常实用的功能。

执行一次性命令

ssh -i ~/.ssh/id_mail study@192.168.2.207 -p 2222 ping 192.168.2.1

这条命令前部分是登录目标机器然后自动执行ping命令,ping命令执行完了就结束本次通信;这里只是一个例子,你可以在最后指定任何命令。

参数:-i 定一个私钥文件为这次通信加解密,如果只生成一个密钥对就不需要在后面指定秘钥文件,默认就会使用那一个;-p指定端口。

上传文件夹

假定远程服务器带宽有限,目标是拷贝时不将服务带宽占满影响正常用户体验。

tar -cj dir/ | pv | cstream -t 100k | ssh study@192.168.2.207 'tar -xj'

将本地 dir/ 限速 100K/s 上传到 192.168.2.207 study账号的主目录下

执行步骤:

  1. tar -cj dir/生成 tar 包并压缩
  2. pv显示传输过程中对带宽的占用情况
  3. cstream -t 100K限速为 100K/s
  4. 'tar -xj'解压上传的tar包

远程目录挂载

  • 临时:将 192.168.2.207 上的/path/目录通过 study 账号临时挂载到本机的/mnt目录下
sshfs study@192.168.2.207:/path/ /mnt 

使用 root 账号卸载

umount /mnt/myfiles

使用普通用户权限卸载

fusermount -u /mnt/myfiles
  • 持久挂载:将 1.1.1.1 上的/path目录通过 user 账号持久挂载到本机的/mntpoint目录下

编辑配置文件:sudo vim /etc/fstab

user@1.1.1.1:/path    /mntpoint    fuse,sshfs    rw,noauto,users,_netdev 0

端口转发

SSH 端口转发也属于 SSH 应用,但是它很实用就单独拎出一章来。

SSH 端口转发分为三种:本地端口转发,远程端口转发及动态端口转发。

常用的命令参数有:

  • -C:压缩数据传输。
  • -f:后台认证用户/密码,通常和 -N 连用,不用登录到远程主机。
  • -N:不执行脚本或命令,通常与 -f 连用。
  • -g:在 -L / -R / -D 参数中,允许远程主机连接到建立的转发的端口(即共享给他人),如果不加这个参数,只允许本地主机建立连接。
  • -L:用于本地端口转发,具体用法在后文阐述。
  • -R:用于远程端口转发,具体用法在后文阐述。
  • -D:用于动态端口转发,具体用法在后文阐述。

注意:不管是本地端口转发,远程端口转发及动态端口转发都需要使用 SSH 服务端的root账号来建立连接。

本地端口转发

ssh -L [收听接口:]收听端口:目标主机:目标端口 username@hostname
  • 本机 IP 可以省略,默认为 0.0.0.0,如果你有多块网卡可以单独指定。
  • 本地端口就是你手头这台机子的端口
  • 目标 IP 是相对于你连接的 SSH 服务端来说的。假设你连接的 SSH 服务端 IP 是 1.1.1.1,你的目标 IP 写为localhost,此时localhost不是代表你手头的这台机器,而是远程 SSH 服务端所在的 1.1.1.1 这台机器。
  • 目标端口,即目标 IP 的端口

如果要建立多条本地端口转发,多加几个 -L 参数即可。

假设有如下的场景一:

你家里有一台电脑,处于局域网中,内网 IP 为:192.168.1.32;你在某某云上有一台服务器,公网 IP 为:1.1.1.1。

现在你想要实现的目标是:访问本机的2001端口相当于在访问 1.1.1.1 上的23端口;在其它地方用别的电脑访问 1.1.1.1 的23端口相当于在访问本机的2001端口。

执行如下命令:

ssh -CfN -L 192.168.1.32:2001:localhost:23 study@1.1.1.1

SSH 本地端口转发一

执行这条端口转发命令后,将会在本机 SSH 客户端 192.168.1.32 与 SSH 服务端 1.1.1.1 之间建立一条 SSH 隧道。

把请求数据比作水,这条 SSH 隧道就好比一根水管,你从2001端口这边灌水进去会从23端口那边出来,反之你往23端口这边灌水进去,会从2001端口这边流出来。

其中192.168.1.32:可以省略,默认为0.0.0.0,如果你电脑上有好几块网卡,你只想在其中一块网卡上建立本地端口转发,那么可以加上本地 IP;之后的例子中就省略掉此部分了。

假设有如下的场景二:

你家里有主机 A,内网 IP 为 192.168.1.32;公司有跳板机 B,公网 IP 为:1.1.1.1;公司还有 WEB 服务器 C,内网 IP 为:10.0.0.1。

主机 A 可以访问跳板机 B,跳板机 B 和 WEB 服务器 C 之间可以互相访问。

现在你想要实现的目标是:访问本机 A 的2001端口就相当于在访问 WEB 服务器 C 的80端口(丐版 VPN)。

执行如下命令:

ssh -CfN -L 2001:10.0.0.1:80 jump@1.1.1.1

SSH 本地端口转发二

执行这条端口转发命令后,将会在本机 SSH 客户端 A 192.168.1.32 与 跳板机 B 之间建立一条 SSH 隧道。

所有访问本机 A 2001端口的数据都将由这条隧道转发给跳板机 B,然后再由跳板机 B 将数据发送到 WEB 服务器 C 的80端口,然后 WEB 服务器 B 80端口返回的数据再顺着这条通道逆向发送到本机 A 的 2001 端口上。

这样就实现了访问本机的2001端口相当于在访问 WEB 服务器的 10.0.0.1 的80端口。

远程端口转发

ssh -R 目标端口:本地IP:本机端口 username@hostname
  • 目标端口,即 hostname 的端口。
  • 本地 IP 是相对于你手头上的这台机子,可以写127.0.0.1表示你手头上的这台机子;也可以写10.0.0.10表示你所在内网的一台机器,访问这台机器的请求和响应将由你手头上的这台机子来进行转发。
  • 本地端口就是你手头这台机子的端口。

如果要建立多条远程端口转发,多加几个 -R 参数即可。

重要:使用远程端口转发需要编辑 SSH 服务端上的 /etc/ssh/sshd_config文件,在其中添加或修改GatewayPorts yes,然后重启sshd.service服务;否则远程端口即 SSH 服务端上只会监听 127.0.0.1 这个 IP,导致其它机器无法访问到远程映射的端口。

假设有如下的场景:

你家里有一台主机 A,内网 IP 为:192.168.1.32;跳板机 B,公网 IP 为:1.1.1.1;公司有 WEB 服务器 C,内网 IP 为:10.0.0.1;及数据库服务器 D,IP 为 10.0.0.2。

它们之间的访问关系是:主机 A 和 WEB 服务器 C 都可以访问跳板机 B,反之则不行;数据库服务器 D 只能由 WEB 服务器 C 来进行访问。

网络拓扑如下:

SSH 远程端口转发案例网络拓扑

现在你想要实现的目标是:访问跳板机 B 的2001端口相当于在访问 WEB 服务器 C 的 80 端口;访问跳板机 B 的2002端口相当于在访问数据库服务器的3306端口。

为了实现此目标你可以在 WEB 服务器 C 上执行 SSH 远程端口转发命令:

ssh -CfN -R 2001:localhost:80 -R 2002:10.0.0.2:3306 jump@1.1.1.1

SSH 远程端口转发

执行这条端口转发命令后,将会在 WEB 服务器 C 和跳板机 B 之间建立一条 SSH 隧道。

当使用主机 A 访问跳板机 B 的2001端口时会将请求通过 SSH 隧道转发到 WEB 服务器 C 的80端口上,80返回的数据顺着这条路原路发送回主机 A上。

当使用主机 A 访问跳板机 B 的2002端口时会将请求通过 SSH 隧道转发到 WEB 服务器 C 上,然后再有 WEB 服务器 C 将请求数据发送到数据库服务器 D 的3306端口上,3306返回的数据顺着这条路原路发送回主机 A 上。

以上就是 SSH 远程转发的案例。

其实如果只需要用主机 A 访问 WEB 服务器 C,也可以通过 WEB 服务器 C 与跳板机 B 之间建立一个本地端口转发,在 WEB 服务器 C 上执行:

ssh -CfN -L 80:localhost:2001 jump@1.1.1.1

连接建立起之后,用主机 A 访问跳板机 B 的2001端口依旧能访问到 WEB 服务器上的80端口。

在这方面远程端口转发和本地端口转发是很类似的,但是对于数据库服务器 D 的访问则必须建立远程端口转发才可以。

动态端口转发

前面的两种转发都需要事先确定要映射的端口,而动态端口转发,顾名思义就是不需要实现指定端口。

其原理是在 SSH 服务端开启一个SOCKS代理(默认是 scoks 5),至于要访问什么网站,完全是动态的,取决于原始通信。相当于将 SSH 服务器变成了一个代理服务器(丐版魔法)。

ssh -D [本机IP:]本地端口 username@hostname
  • 本机 IP 可以省略,默认为 0.0.0.0,如果你有多块网卡可以单独指定。
  • 本地端口就是你手头这台机子的端口

假设有如下的场景:

你家里有一台主机 A,内网 IP 为:192.168.1.32;云服务器 B,公网 IP 为:1.1.1.1。

由于你家里的网络条件不是很好,现在你想要通过云服务器 B 来进行代理上网。

那么你可以执行:

ssh -CfN -D 2001 study@1.1.1.1

执行成功后会在本机的2001端口与1.1.1.1建立一个动态转发,将浏览器的代理设置为本机的2001端口,代理类型选择socks 5之后,访问 baidu.com 的流量顺序是:

localhost:2001 --> localhost:22 --> 1.1.1.1:22 --> baidu.com:80

可以看到请求的流量都是走 SSH 隧道,会经过加密,所以是非常安全的。响应的数据也同理,按照原路返回。

思路打开,如果在云服务器 B 上执行上面那条命令,会发生什么呢?这会让云服务 B 对自身进行动态端口转发,使它成为一个任何人都可以访问的代理服务器。

保持转发不掉线

在建立端口转发隧道后,如果一段时间内没有使用,可能会导致连接断开的情况。为了解决这个问题,可以使用 autossh 工具来维持隧道并实现自动重新连接的功能。

以下命令在 root 账号下执行。

  1. 安装 autossh

    apt update
    apt install autossh
    
  2. 编辑 autossh 服务文件

    vim /etc/systemd/system/autossh.service
    

    填入以下内容并保存:

    [Unit]
    Description=AutoSSH Service
    After=network-online.target
    
    [Service]
    User=root
    ExecStart=/usr/bin/autossh -M 0 -CN -R 2001:localhost:22 root@1.1.1.1
    
    [Install]
    WantedBy=multi-user.target
    

    在 ExecStart 部分填写 ssh 端口转发命令,- M 0是 autossh 命令的参数,表示不开启监视端口;其它参数是 ssh 命令命令的参数。

    -M 参数在 autossh 命令中用于指定一个监视端口,以便自动 SSH 会话在远程主机上建立一个用于检测连接状态的隧道。这个监视端口通常用于确保 SSH 连接的稳定性,如果 SSH 连接断开,那么监视端口也会关闭,从而触发 autossh 重新建立连接。

    注意:不能在 ExecStart 中添加 ssh 端口转发的 -f 参数。

  3. 重新加载服务配置文件

    systemctl daemon-reload
    
  4. 启动 autossh 服务并设置开机自启

    # 启动 autossh 服务
    systemctl start autossh.service
    
    # 设置开机自启
    systemctl enable autossh.service
    

防爆破

任何连接到互联网的机器都是恶意攻击的潜在目标。 有一个名为 Fail2Ban 的工具可用来缓解服务器上的非法访问。

安装

sudo apt install fail2ban

fail2ban的工作原理是每隔一段时间读取分析日志文件,如果有异常 IP 则会禁用它。

注意:每次在重启的时候都会重新读取一次日志文件,可能造成的影响是你刚刚解禁了一个 IP,然后你重启了fail2ban,这个 IP 又被禁用了。

配置

默认配置文件/etc/fail2ban/jail.conf在软件更新时会被覆盖

/etc/fail2ban/jail.conf复制一份作为本地配置文件,命名为/etc/fail2ban/jail.local,优先级高于默认配置文件。

全局配置项

lgnoreip = 127.0.0.1/8 192.168.1.245/24    # 忽略地址/地址段(不禁止这些地址),密码错多少次都不会禁止它
bantime = -1    # 后面加的是时间(秒),当有人连续输错密码超过指定次数后禁止多长时间,-1表示永久禁止
findtime = 600  # 每隔 600 秒检查一次日志,检查到异常 IP 后就 ban
maxretry = 5    # 最大连续错误尝试 5 次

配置 sshd 开启 Jail

SSH防爆破

常用命令

  • 查看总览
sudo fail2ban-client status
  • 查看配置项执行详细信息
sudo fail2ban-client status sshd
  • 查看防火墙规则
sudo iptables -L -n
  • 手动解除被禁 IP

使用iptables手动删除对192.168.2.190的防火墙规则

sudo iptables -D f2b-sshd -s 192.168.2.190-j REJECT

参数-D表示删除规则;f2b-sshd为规则名称;-s要解除的ip地址;j REJECT拒绝的方式是REJECT,后面写自己防火墙禁用的方式。

使用fail2ban解除对192.168.2.190禁用

sudo fail2ban-client set sshd unbanip 192.168.2.190

参考资料

2

评论区