SSH完全使用教程

Kevin2li大约 8 分钟Linuxssh

简介

SSH(安全外壳协议)是一种加密的网络传输协议,可在不安全的网络中为网络服务提供安全的传输环境。它通过在网络中创建安全隧道来实现SSH客户端和服务器之间的连接。最早的时候,互联网通信都是明文通信,一旦被截获,内容就会被暴露。1995年,芬兰学者Tatu Ylonen设计了SSH协议,将登录信息全部加密,成为互联网安全的一个基本解决方案,迅速在全世界获得推广,目前已经成为所有操作系统的标准配置。

安装

Windows

  1. Openssh

安装 OpenSSH

参考:安装 OpenSSH | Microsoft Learnopen in new window

若要安装 OpenSSH 组件:

  1. 打开"设置",选择"应用">"应用和功能",然后选择"可选功能" 。

image.png 2. 扫描列表,查看是否已安装 OpenSSH。 如果未安装,请在页面顶部选择"添加功能",然后:

  • 查找"OpenSSH 客户端",再单击"安装"\
  • 查找"OpenSSH 服务器",再单击"安装"

设置完成后,回到"应用">"应用和功能"和"可选功能",你应会看到已列出 OpenSSH。

  1. Copssh

Copssh功能更全面,弥补了上面Openssh在某些参数上不支持的不足(如ControlMaster等)。

Copssh介绍

Copssh 是一个用于 Windows 系统的 OpenSSH 服务器和客户端实现。它打包了便携式 OpenSSH、Cygwin 和一些流行的实用程序,并实现了一些关于安全性的最佳实践。您可以使用 Copssh 进行远程管理您的系统或以安全的方式收集远程信息。

官网:https://www.itefix.net/copsshopen in new window

Ubuntu

很多设备默认都安装了ssh客户端程序,如果需要让别的机器登录到本机,则还需要安装服务端程序。

sudo apt install openssh-server

常用命令

基本参数介绍

image.png
image.png

常用参数

  • -C: 数据压缩
  • -f:后台运行
  • -N: 只转发端口,不执行远程命令
  • -g: 允许远程主机连接到本地转发端口
  • -T: 禁止终端分配
  • -J: 设置跳板机
  • -X: 允许x11转发
  • -v:显示详细日志
  • -o: 设置选项,如-o Port=22
# 举例:本地端口转发
ssh -CNfTL 9999:localhost:8000 user@host

# 举例:远程端口转发(使用场景:可以在云服务器上使用本机的科学上网代理)
ssh -CNfTR 9150:localhost:8888 temp@39.108.XXX.XXX

登录

直接登录

# Connect to a remote server:
ssh {{username}}@{{remote_host}}

# Connect to a remote server with a specific identity (private key):
ssh -i {{path/to/key_file}} {{username}}@{{remote_host}}

# Connect to a remote server using a specific port:
ssh {{username}}@{{remote_host}} -p {{2222}}

使用代理登录

为了能够从外部访问内网的机器,有时需要进行内网穿透,将内网机器的ssh端口映射到一台公网机器的指定端口上,但是这样很有可能会遭到外网的恶意机器通过公网暴露的端口对内网机器进行弱口令爆破。安全起见,公网机器的端口暴露越少越好,因此考虑设置代理服务器,让自己的受信任设备通过代理服务器登录,这样映射的ssh端口可以不用暴露到公网,只用暴露代理服务器的一个端口即可。

  1. 云服务器搭建socks代理服务

参考:https://www.digitalocean.com/community/tutorials/how-to-set-up-dante-proxy-on-ubuntu-20-04open in new window

  1. 安装:
sudo apt update
sudo apt install dante-server
  1. 验证:
systemctl status danted.service
  1. 配置

配置文件路径:/etc/danted.conf

logoutput: syslog
user.privileged: root
user.unprivileged: nobody

# The listening
network interface or address.
internal: 0.0.0.0 port=10080

# The proxying network interface or address.
external: eth0

# socks-rules determine what is proxied through the external interface.
socksmethod: username

# client-rules determine who can connect to the internal interface.
clientmethod: none

client pass {
    from: 0.0.0.0/0 to: 0.0.0.0/0
}

socks pass {
    from: 0.0.0.0/0 to: 0.0.0.0/0
}

重启服务:

sudo systemctl restart danted.service
  1. 开放端口:
# 端口与配置文件指定的端口一致
sudo firewall-cmd --permanent --zone=public --add-port 10080/tcp
sudo firewall-cmd --reload
  1. 创建用户
sudo useradd -r -s /bin/false your_dante_user
sudo passwd your_dante_user
  1. 测试
curl -v -x socks5://your_dante_user:your_dante_password@your_server_ip:10080 http://www.baidu.com/
  1. 客户端登录
  1. 安装ncat
  • Ubuntu
sudo apt update
sudo apt install ncat
  • Windows

下载: https://nmap.org/download.html#windowsopen in new window

  1. 连接:
  • 命令行:
ssh -o "ProxyCommand ncat --proxy-type socks5 --proxy <proxy_ip>:<proxy_port> %h %p --proxy-auth <proxyuser>[:pass]" -p 11005 kevin2li@localhost
  • 配置文件:~/.ssh/config:
Host PC
    HostName localhost
    Port 11005
    User kevin2li
    ProxyCommand ncat --proxy-type socks5 --proxy <proxy_ip>:<proxy_port> %h %p --proxy-auth <proxy_user>:<password>

可使用下面命令连接:

ssh PC

密钥管理

生成密钥

ssh-keygen -t ed25519 -C "your_email@example.com"

# If you are using a legacy system that doesn't support the Ed25519 algorithm, use:
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"

拷贝密钥到服务器

  • Linux
# Copy your keys to the remote machine:
ssh-copy-id {{username@remote_host}}

# Copy the given public key to the remote:
ssh-copy-id -i {{path/to/certificate}} {{username}}@{{remote_host}}

# Copy the given public key to the remote with specific port:
ssh-copy-id -i {{path/to/certificate}} -p {{port}} {{username}}@{{remote_host}}
  • Windows

方式一:

# ed25519公钥
cat $env:USERPROFILE\.ssh\id_ed25519.pub | ssh {{username}}@{{remote_host}} "cat - >> .ssh/authorized_keys"

# rsa公钥
cat $env:USERPROFILE\.ssh\rsa.pub | ssh {{username}}@{{remote_host}} "cat - >> .ssh/authorized_keys"

方式二:

# ed25519公钥
ssh {{username}}@{{remote_host}}  "cat - >> ~/.ssh/authorized_keys" <  ~/.ssh/id_ed25519.pub

# rsa公钥
ssh {{username}}@{{remote_host}}  "cat - >> ~/.ssh/authorized_keys" <  ~/.ssh/id_rsa.pub

隧道搭建

参考:https://phoenixnap.com/kb/ssh-port-forwardingopen in new window

本地转发

作用:将本地端口的请求转发的远程主机上

格式:

ssh -L local_port:destination_server_ip:remote_port ssh_server_hostname

举例:

ssh –L 5901:188.17.0.5:4492 pnap@ssh.server.com

远程转发

作用:将远程端口的请求转发的本地主机上
格式:

ssh -R remote_port:localhost:local_port ssh_server_hostname

举例:

ssh –R 8080:localhost:5534 pnap@ssh.server.com

动态转发

作用:可视为本地转发特殊形式,本地转发是一对一,这个可以一对多

格式:

ssh –D local_port ssh_server_hostname

举例:

ssh –D 5534 pnap@ssh.server.com

::: tip{title="使用场景举例"} 可以将其作为代理使用,如图,主机A通过主机B代理上外网:

drawio.png
drawio.png
# hostA执行
ssh -D 9999 userB@hostB
# hostA测试
curl -v -x socks5://localhost:9999 https://www.baidu.com

将本地主机A发往9999端口的网络请求通过隧道传输到主机B,主机B解析出网络请求的目标地址后,代理访问目标并将结果通过隧道返回给主机A。

注意:为了使所有的网络请求走代理进入隧道,需要在系统设置或浏览器设置里配置好socks代理 :::

X协议转发

作用:将服务器上带有图形化界面(GUI)的程序转发到本地

参考: https://kb.iu.edu/d/bdntopen in new window

文件传输

  • scp
# Copy a local file to a remote host:
scp {{path/to/local_file}} {{remote_host}}:{{path/to/remote_file}}

# Use a specific port when connecting to the remote host:
scp -P {{port}} {{path/to/local_file}} {{remote_host}}:{{path/to/remote_file}}

# Copy a file from a remote host to a local directory:
scp {{remote_host}}:{{path/to/remote_file}} {{path/to/local_directory}}

# Recursively copy the contents of a directory from a remote host to a local directory:
scp -r {{remote_host}}:{{path/to/remote_directory}} {{path/to/local_directory}}

# Copy a file between two remote hosts transferring through the local host:
scp -3 {{host1}}:{{path/to/remote_file}} {{host2}}:{{path/to/remote_directory}}

# Use a specific username when connecting to the remote host:
scp {{path/to/local_file}} {{remote_username}}@{{remote_host}}:{{path/to/remote_directory}}

# Use a specific ssh private key for authentication with the remote host:
scp -i {{~/.ssh/private_key}} {{local_file}} {{remote_host}}:{{/path/remote_file}}
  • rsync
# Transfer file from local to remote host:
rsync {{path/to/local_file}} {{remote_host}}:{{path/to/remote_directory}}

# Transfer file from remote host to local:
rsync {{remote_host}}:{{path/to/remote_file}} {{path/to/local_directory}}

# Transfer file in [a]rchive (to preserve attributes) and compressed ([z]ipped) mode with [v]erbose and [h]uman-readable [P]rogress:
rsync -azvhP {{path/to/local_file}} {{remote_host}}:{{path/to/remote_directory}}

# Transfer a directory and all its children from a remote to local:
rsync -r {{remote_host}}:{{path/to/remote_directory}} {{path/to/local_directory}}

# Transfer directory contents (but not the directory itself) from a remote to local:
rsync -r {{remote_host}}:{{path/to/remote_directory}}/ {{path/to/local_directory}}

# Transfer a directory [r]ecursively, in [a]rchive to preserve attributes, resolving contained soft[l]inks , and ignoring already transferred files [u]nless newer:
rsync -rauL {{remote_host}}:{{path/to/remote_directory}} {{path/to/local_directory}}

# Transfer file over SSH and delete remote files that do not exist locally:
rsync -e ssh --delete {{remote_host}}:{{path/to/remote_file}} {{path/to/local_file}}

# Transfer file over SSH using a different port than the default and show global progress:
rsync -e 'ssh -p {{port}}' --info=progress2 {{remote_host}}:{{path/to/remote_file}} {{path/to/local_file}}
  • sshfs

安装:

# For Ubuntu
sudo apt update
sudo apt install sshfs

挂载目录:

参考:How To Use SSHFS to Mount Remote File Systems Over SSHopen in new window

sudo mkdir /mnt/droplet
sudo sshfs -o allow_other,default_permissions sammy@your_other_server:~/ /mnt/droplet

跳板机

参考: https://goteleport.com/blog/ssh-proxyjump-ssh-proxycommand/open in new window

  • 命令行
# 使用ProxyJump(推荐)
ssh -J <jump server1>,<jump server2>,<jump server3> <remote server>
ssh -J <user@jump-host:port> <user@remote-target:port> <remote server>
# e.g.
ssh -J kevin2li@192.168.2.121 -p 24 likai@10.14.132.126

# 使用ProxyCommand
ssh -o ProxyCommand="ssh -W %h:%p <jump server>" <remote server>
# e.g.
ssh -o ProxyCommand="ssh -W %h:%p kevin2li@192.168.2.121" -p 24 likai@10.14.132.126
  • 配置文件

场景:

image.png
image.png

在配置文件~/.ssh/config中可按如下配置:

Host remoteserver
  HostName 192.168.200.200
  User dev
  IdentityFile ~/.ssh/<your_key>
  Port 2048
  ProxyJump jumpserver

Host jumpserver
  Hostname <jumpserver_ip>
  User <user_name>

使用下面命令即可登录:

ssh remoteserver

配置文件

系统服务配置文件

配置文件路径:/etc/ssh/sshd_config

常用配置:

Port 22
PubkeyAuthentication yes
# PermitRootLogin yes

# 是否允许密码登录:To disable tunneled clear text passwords, change to no here!
PasswordAuthentication no

X11Forwarding yes

# 保活
ClientAliveInterval 60
ClientAliveCountMax 60

个人配置文件

配置文件路径:~/.ssh/config

示例如下:

Host *
  TCPKeepAlive yes
  Compression yes
  ForwardAgent yes
  IdentityFile ~/.ssh/id_ed25519
  
  # 保活
  ServerAliveInterval 60
  ServerAliveCountMax 60
  
  # 多路复用(windows暂不支持)
  # ControlMaster auto
  # ControlPath ~/.ssh/control:%h:%p:%r
  # ControlPersist 1h
  
Host Server
  HostName 192.168.2.121
  User kevin2li
  Port 22

完整参数可详见:https://man.openbsd.org/ssh_config.5open in new window

::: info{title="SSH多路复用"} 参考:https://docs.cci.rpi.edu/examples/Advanced_SSH/open in new window :::

这样就可以通过下面命令简化登录:

ssh Lab

日志查看

journalctl -u ssh

# 查看最近登陆的记录
last

# 查看到登陆失败的记录
lastb

# 查看最近登陆的记录
lastlog

# 检查当前在线用户
who

可以检查的文件:

  • /var/log/auth.log
  • /var/log/secure

安全增强

为了防止被弱口令爆破,常见的可以通过修改默认登录端口、关闭密码登录方式、使用第三方拦截软件等方式来提高安全性。

1. 修改SSH默认的22端口

  1. 编辑配置文件/etc/ssh/sshd_config:
sudo vim /etc/ssh/sshd_config
  1. 修改配置文件:
# 改为>1024的其他端口号
Port 8022
  1. 重启sshd服务
sudo systemctl restart sshd

2. 关闭密码登录,采用密钥登录

  1. 编辑配置文件/etc/ssh/sshd_config:
sudo vim /etc/ssh/sshd_config
  1. 修改配置文件:
# 禁用密码验证
PasswordAuthentication no

# 启用密钥验证
PubkeyAuthentication yes
  1. 重启sshd服务
sudo systemctl restart sshd
  1. 验证:

通过密码登录被拒绝,则为成功。

image.png
image.png

3. 使用第三方的拦截软件

比如:Fail2banopen in new window