OpenSSH是基於Secure Shell協議的安全套件,通過加密網絡流量實現網絡通信安全,主要於遠程連接。同時提供創建安全隧道(tunnel)、多重認證機制等功能。

OpenSSH由以下套件組成:

  1. 遠程操作工具: ssh, scpsftp
  2. 密鑰管理工具: ssh-add, ssh-keysign, ssh-keyscanssh-keygen
  3. 服務器端工具: sshd, sftp-serverssh-agent

OpenSSH Installations

OpenSSH的Client和Server在CentOS、Debian等發行版中是2個獨立的安裝包,而在OpenSUSE中,包openssh同時包含二者,只有一個安裝包。

Installing OpenSSH

安裝

1
2
3
4
5
6
7
8
9
10
# CentOS/RedHat
sudo yum install openssh-clients -y
sudo yum install openssh-server -y
# Debian/Ubunut
sudo apt-get install openssh-clients -y
sudo apt-get install openssh-server -y
# OpenSUSE contain server & client side
sudo zpyyer install openssh -y

Disabling OpenSSH Server

卸載

1
2
3
4
5
6
7
8
9
10
11
sudo systemctl stop sshd.service
sudo systemctl disable sshd.service
# CentOS/RedHat
sudo yum erase openssh-server -y
# Debian/Ubunut
sudo apt-get purge openssh-server -y
sudo apt-get autoremove -y
# OpenSUSE

如果配置了防火牆規則,需修改規則後重啓相關服務,如iptablesufw等。

SSH Configuration Files

SSH相關配置文件,可通過如下命令查看

1
man ssh | sed -n '/^FILES/,/^EXIT STATUS/p' | sed '$d'
file
~/.rhosts
~/.shosts
~/.ssh/
~/.ssh/authorized_keys
~/.ssh/config
~/.ssh/environment
~/.ssh/identity
~/.ssh/id_dsa
~/.ssh/id_ecdsa
~/.ssh/id_ed25519
~/.ssh/id_rsa
~/.ssh/identity.pub
~/.ssh/id_dsa.pub
~/.ssh/id_ecdsa.pub
~/.ssh/id_ed25519.pub
~/.ssh/id_rsa.pub
~/.ssh/known_hosts
~/.ssh/rc
/etc/hosts.equiv
/etc/ssh/shosts.equiv
/etc/ssh/ssh_config
/etc/ssh/ssh_host_key
/etc/ssh/ssh_host_dsa_key
/etc/ssh/ssh_host_ecdsa_key
/etc/ssh/ssh_host_ed25519_key
/etc/ssh/ssh_host_rsa_key
/etc/ssh/ssh_known_hosts
/etc/ssh/sshrc

常用配置文件

file explanation
~/.ssh/ 登錄用戶SSH配置文件目錄
~/.ssh/id_rsa 用於遠程登錄認證的私鑰(私有)
~/.ssh/id_rsa.pub 用於遠程登錄認證的公鑰(公開)
~/.ssh/authorized_keys 遠程用戶的用於遠程登錄該主機的公鑰信息
~/.ssh/known_hosts 遠程用戶用於遠程登錄該主機的主機信息
~/.ssh/config 登錄用戶配置文件(rwx 600)
/etc/ssh/ssh_config OpenSSH客戶端配置文件
/etc/ssh/sshd_config OpenSSH服務器端配置文件

文件的讀寫權限

file attribute
~/.ssh/ 700
~/.ssh/id_ed25519 600
~/.ssh/id_ed25519.pub 644
~/.ssh/known_hosts 644
~/.ssh/authorized_keys 600

  1. SSH默認端口號是TCP 22
  2. 目錄~/表示登錄用戶家目錄$HOME
  3. 如果文件/etc/nologin存在,則sshd拒絕任何用戶登錄(root用戶除外);
  4. 如果遠程主機安裝了tcp-wrappers,則會生成文件/etc/hosts.allow/etc/hosts.deny,用於訪問控制

可通過如下命令查看SSH支持的密碼算法

1
ssh -Q {cipher | cipher-auth | mac | kex | key}

Configurations Optimization

參數修改的出發點是提升OpenSSH安全性,主要參考Security/Guidelines/OpenSSH – MozillaTop 20 OpenSSH Server Best Security Practices(含有防火牆iptables配置),推薦閱讀。

可使用如下命令生成強密碼

1
2
3
4
5
6
7
len=20
# method 1
tr -dc A-Za-z0-9_ < /dev/urandom | head -c $len | xargs
# method 2
openssl rand -base64 $len

sshd_config Optimization

文件/etc/ssh/sshd_config中各指令的說明可通過如下命令查看

1
man 5 sshd_config

參數針對最新OpenSSH版本設置,不特意兼容舊版本。執行如下命令進行參數修改(不更改默認端口號22)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# Only Use SSH Protocol 2
sudo sed -i -r 's@^#?(Protocol 2)@\1@' /etc/ssh/sshd_config
# Limit Users' SSH Access, separated by spaces
# DenyUsers > AllowUsers > DenyGroups > AllowGroups
# Log Out Timeout Interval, just work for Protocol 2
[[ ! -z $(sed -n -r '/^#?ClientAliveCountMax/p' /etc/ssh/sshd_config) ]] && sudo sed -i -r 's@^#?(ClientAliveCountMax).*@\1 0@' /etc/ssh/sshd_config || sudo sed -i -r '$a ClientAliveCountMax 0' /etc/ssh/sshd_config
[[ ! -z $(sed -n -r '/^#?ClientAliveInterval/p' /etc/ssh/sshd_config) ]] && sudo sed -i -r 's@^#?(ClientAliveInterval).*@\1 180@' /etc/ssh/sshd_config || sudo sed -i -r '$a ClientAliveInterval 180' /etc/ssh/sshd_config
# Disallow the system send TCP keepalive messages to the other side
[[ ! -z $(sed -n -r '/^#?TCPKeepAlive/p' /etc/ssh/sshd_config) ]] && sudo sed -i -r 's@^#?(TCPKeepAlive).*@\1 no@' /etc/ssh/sshd_config || sudo sed -i -r '$a TCPKeepAlive no' /etc/ssh/sshd_config
# Don't read the user's ~/.rhosts and ~/.shosts files
[[ ! -z $(sed -n -r '/^#?IgnoreRhosts/p' /etc/ssh/sshd_config) ]] && sudo sed -i -r 's@^#?(IgnoreRhosts).*@\1 yes@' /etc/ssh/sshd_config || sudo sed -i -r '$a IgnoreRhosts yes' /etc/ssh/sshd_config
# Use Public Key Based Authentication
[[ ! -z $(sed -n -r '/^#?PubkeyAuthentication/p' /etc/ssh/sshd_config) ]] && sudo sed -i -r 's@^#?(PubkeyAuthentication).*@\1 yes@' /etc/ssh/sshd_config || sudo sed -i -r '$a PubkeyAuthentication yes' /etc/ssh/sshd_config
# Just Allow Public Key Authentication Login
[[ ! -z $(sed -n -r '/^#?AuthenticationMethods/p' /etc/ssh/sshd_config) ]] && sudo sed -i -r 's@^#?(AuthenticationMethods).*@\1 publickey@' /etc/ssh/sshd_config || sudo sed -i -r '$a AuthenticationMethods publickey' /etc/ssh/sshd_config
# Disable Host-Based Authentication
[[ ! -z $(sed -n -r '/^#?HostbasedAuthentication/p' /etc/ssh/sshd_config) ]] && sudo sed -i -r 's@^#?(HostbasedAuthentication).*@\1 no@' /etc/ssh/sshd_config || sudo sed -i -r '$a HostbasedAuthentication no' /etc/ssh/sshd_config
# Disable root Login via SSH {yes,without-password,forced-commands-only,no}
[[ ! -z $(sed -n -r '/^#?PermitRootLogin/p' /etc/ssh/sshd_config) ]] && sudo sed -i -r 's@^#?(PermitRootLogin).*@\1 no@' /etc/ssh/sshd_config || sudo sed -i -r '$a PermitRootLogin no' /etc/ssh/sshd_config
# Disable Password Authentication
[[ ! -z $(sed -n -r '/^#?PasswordAuthentication/p' /etc/ssh/sshd_config) ]] && sudo sed -i -r 's@^#?(PasswordAuthentication).*@\1 no@' /etc/ssh/sshd_config || sudo sed -i -r '$a PasswordAuthentication no' /etc/ssh/sshd_config
# Disallow Empty Password Login
[[ ! -z $(sed -n -r '/^#?PermitEmptyPasswords/p' /etc/ssh/sshd_config) ]] && sudo sed -i -r 's@^#?(PermitEmptyPasswords).*@\1 no@' /etc/ssh/sshd_config || sudo sed -i -r '$a PermitEmptyPasswords no' /etc/ssh/sshd_config
# Enable a Warning Banner After Login, just change /etc/motd
# Enable a Warning Banner Before Login, default none
[[ ! -z $(sed -n -r '/^#?Banner/p' /etc/ssh/sshd_config) ]] && sudo sed -i -r 's@^#?(Banner).*@\1 /etc/ssh/banner@' /etc/ssh/sshd_config || sudo sed -i -r '$a Banner /etc/ssh/banner' /etc/ssh/sshd_config
sed -r -n [email protected]_NAME="(.*)"@\[email protected]' /etc/os-release | sudo tee /etc/ssh/banner
# Enable Logging Message {QUIET, FATAL, ERROR, INFO, VERBOSE, DEBUG, DEBUG1, DEBUG2, DEBUG3}
[[ ! -z $(sed -n -r '/^#?LogLevel/p' /etc/ssh/sshd_config) ]] && sudo sed -i -r 's@^#?(LogLevel).*@\1 VERBOSE@' /etc/ssh/sshd_config || sudo sed -i -r '$a LogLevel VERBOSE' /etc/ssh/sshd_config
# Turn on privilege separation
[[ ! -z $(sed -n -r '/^#?UsePrivilegeSeparation/p' /etc/ssh/sshd_config) ]] && sudo sed -i -r 's@^#?(UsePrivilegeSeparation).*@\1 sandbox@' /etc/ssh/sshd_config || sudo sed -i -r '$a UsePrivilegeSeparation sandbox' /etc/ssh/sshd_config
# Check file modes and ownership of the user's files and home directory before accepting login
[[ ! -z $(sed -n -r '/^#?StrictModes/p' /etc/ssh/sshd_config) ]] && sudo sed -i -r 's@^#?(StrictModes).*@\1 yes@' /etc/ssh/sshd_config || sudo sed -i -r '$a StrictModes yes' /etc/ssh/sshd_config
# Ciphers Setting
[[ ! -z $(sed -n -r '/^#?Ciphers.*aes.*/p' /etc/ssh/sshd_config) ]] && sudo sed -i -r 's@^#?(Ciphers).*@\1 [email protected],[email protected],[email protected],aes256-ctr,aes192-ctr,aes128-ctr@' /etc/ssh/sshd_config || sudo sed -i -r '$a Ciphers [email protected],[email protected],[email protected],aes256-ctr,aes192-ctr,aes128-ctr' /etc/ssh/sshd_config
# Supported HostKey algorithms by order of preference
sudo sed -i -r 's@^#?(HostKey /etc/ssh/ssh_host_dsa_key)$@#\1@' /etc/ssh/sshd_config
sudo sed -i -r 's@^#?(HostKey /etc/ssh/ssh_host_rsa_key)$@\1@' /etc/ssh/sshd_config
sudo sed -i -r 's@^#?(HostKey /etc/ssh/ssh_host_ecdsa_key)$@\1@' /etc/ssh/sshd_config
sudo sed -i -r 's@^#?(HostKey /etc/ssh/ssh_host_ed25519_key)$@\1@' /etc/ssh/sshd_config
# Specifies the available KEX (Key Exchange) algorithms
sudo sed -i -r '/^#?KexAlgorithms/d;$a KexAlgorithms [email protected],ecdh-sha2-nistp521,ecdh-sha2-nistp384,ecdh-sha2-nistp256,diffie-hellman-group-exchange-sha256' /etc/ssh/sshd_config
# Message authentication codes (MACs) Setting
sudo sed -i -r '/^#?MACs/d;$a MACs [email protected],[email protected],[email protected],[email protected],hmac-sha2-512,hmac-sha2-256,hmac-ripemd160,[email protected]' /etc/ssh/sshd_config
#此處禁止TCP端口、X11轉發
# Disable TCP Port forwarding {yes,no,local,remote}
[[ ! -z $(sed -n -r '/^#?AllowTcpForwarding/p' /etc/ssh/sshd_config) ]] && sudo sed -i -r 's@^#?(AllowTcpForwarding).*@\1 no@' /etc/ssh/sshd_config || sudo sed -i -r '$a AllowTcpForwarding no' /etc/ssh/sshd_config
# Disable X11 forwarding
[[ ! -z $(sed -n -r '/^#?X11Forwarding/p' /etc/ssh/sshd_config) ]] && sudo sed -i -r 's@^#?(X11Forwarding).*@\1 no@' /etc/ssh/sshd_config || sudo sed -i -r '$a X11Forwarding no' /etc/ssh/sshd_config

ssh_config Optimization

文件~/.ssh/config中各指令的說明可通過如下命令查看

1
man 5 ssh_config

執行如下命令進行參數修改

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
touch ~/.ssh/config
chmod 600 ~/.ssh/config
tee ~/.ssh/config <<-EOF
# Ensure KnownHosts are unreadable if leaked - it is otherwise easier to know which hosts your keys have access to.
HashKnownHosts yes
# Host keys the client accepts - order here is honored by OpenSSH
HostKeyAlgorithms [email protected],[email protected],ssh-ed25519,ssh-rsa,[email protected],[email protected],[email protected],ecdsa-sha2-nistp521,ecdsa-sha2-nistp384,ecdsa-sha2-nistp256
KexAlgorithms [email protected],ecdh-sha2-nistp521,ecdh-sha2-nistp384,ecdh-sha2-nistp256,diffie-hellman-group-exchange-sha256
MACs [email protected],[email protected],[email protected],hmac-sha2-512,hmac-sha2-256,[email protected]
Ciphers [email protected],[email protected],[email protected],aes256-ctr,aes192-ctr,aes128-ctr
EOF

SSH-Kegen Keys

Generating SSH-Kegen Keys

創建SSH認證密鑰須使用ssh-keygen命令,密鑰類型建議使用RSAED25519,不建議使用DSAECDSA。需要向後兼容的(如CentOS6.8)使用RSA,不需要向後兼容的使用ED25519

生成的密鑰默認保存$HOME/.ssh/中($HOME是用戶家目錄),如果該目錄不存在,則會自動創建,也可通過參數-f手動指定路徑。

執行如下命令創建認證密鑰

1
2
3
4
5
6
# RSA
ssh-keygen -t rsa -b 4096 -f ~/.ssh/id_rsa_$(date +%Y-%m-%d) -C "Comments"
#D25519
# This is only compatible with OpenSSH 6.5+ and fixed-size (256 bytes).
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_$(date +%Y-%m-%d) -C "Comments"

參數解釋

option explanation
-t Specifies the type of key to create.
-b bits Specifies the number of bits in the key to create.
-f Specifies the filename of the key file.
-C comment Provides a new comment.

Installing Public Key To Remote Server

將公鑰安裝到目標主機中,之後再使用SSH遠程連接,無須輸入用戶密碼即可直接登錄,但可能會提示輸入私鑰的passphrase。

安裝方式主要2種,取決於本機是否安裝有ssh-copy-id

  1. 直接使用ssh-copy-id命令安裝
  2. 使用SSH連接,手動創建相關目錄文件

Via ssh-copy-id

語法格式

1
ssh-copy-id [-n] [-i [identity_file]] [-p port] [-o ssh_option] [user@]hostname

執行如下命令

1
ssh-copy-id -i ~/.ssh/id_ed25519.pub -p 22 [email protected]

操作成功後,提示

Now try logging into the machine, with: “ssh [email protected]
and check to make sure that only the key(s) you wanted were added.

在遠程主機[email protected]中的/home/flying目錄下自動創建.ssh/authorized_keys文件,而其內容含有公鑰~/.ssh/id_ed25519.pub中內容。

執行如下命令進行操作

1
2
3
cat $HOME/.ssh/id_ed25519.pub | ssh -p 22 [email protected] '(umask 077; [[ -d ~/.ssh ]] || mkdir ~/.ssh; cat >> ~/.ssh/authorized_keys)'
cat $HOME/.ssh/id_rsa.pub | ssh -p 22 [email protected] '(umask 077; [[ -d ~/.ssh ]] || mkdir ~/.ssh; cat >> ~/.ssh/authorized_keys)'

命令解釋

  • umask 077: 指定掩碼,爲創建目錄、文件指定默認權限,目錄是(777-077=700),文件是(666-077=600)
  • [[ -d ~/.ssh ]]: 測試命令,判斷目錄是否存在
  • mkdir: 創建目錄
  • >>: 追加輸出重定向,文件不存在則自動創建

直接使用

1
ssh -p 22 [email protected]

登錄,提示輸入密鑰密碼後(假如創建密鑰時設置了密碼),即可直接登錄,無需輸入用戶密碼。

SSH Simage Usage

使用ssh操作實例

Execute Remote Script

執行如下命令

1
ssh -p 22 [email protected] 'bash /tmp/test.sh'

解釋: 通過ssh遠程連接主機192.168.0.140:22,用戶名爲flying,執行遠程主機中的腳本/tmp/test.sh

Remote Backup and Restore Compressed Files

使用tar進行歸檔操作,默認使用相對路徑,如果直接使用絕對路徑,會報如下錯誤tar: Removing leading '/' from member names。使用絕對路徑須加參數-p,但不建議,原因是使用絕對路徑,解壓時會出現問題,可能會覆蓋已經存在的文件。

此處假定遠程服務器ip爲192.168.0.140

  • 將本地目錄文件以壓縮包形式保存到遠程服務器
1
2
3
4
5
6
7
cd /home/$nowUser/Documents/
# method 1
tar Jcf - node_hexo/ | ssh -p 22 [email protected] "cat > /tmp/hexo.tar.xz"
# method 2
tar Jcf - node_hexo/ | ssh -p 22 [email protected] "dd of=/tmp/hexo.tar.xz"
  • 將遠程服務器的壓縮包文件解壓到本地指定目錄(/tmp)
1
2
3
4
5
# method 1
ssh -p 22 [email protected] "cat /tmp/hexo.tar.xz" | tar Jxf - -C /tmp
# method 2
ssh -p 22 [email protected] "dd if=/tmp/hexo.tar.xz" | tar Jxf - -C /tmp

注意: tar後的-不可省去,會報錯;-C表示指定解壓縮目錄路徑;dd表示格式化和複製文件

Remote Copy Database Data Cross Server

使用SSH和管道符|實現跨服務器數據複製,命令格式如下

1
mysqldump -uroot -pXXX database_name | ssh [email protected] -pXXX mysql -utianyun -pXXX database_name

具體實例參看本人之前寫的博文

Compare Remote and Locale File

使用SSH、管道符號|diff命令對文件內容進行比較,此使用案例是HA Cluster中比較各節點主機間配置文件內容是否一致

1
ssh node2 'cat /etc/corosync/corosync.conf' | diff - /etc/corosync/corosync.conf

使用diff命,如果內容一致,不輸出任何內容

1
2
3
4
5
6
7
[[email protected] ~]$ ssh node2 'cat /etc/corosync/corosync.conf' | diff - /etc/corosync/corosync.conf
Enter passphrase for key '/home/flying/.ssh/id_rsa':
#命令執行返回0,表示成功
[[email protected] ~]$ echo $?
0
[[email protected] ~]$

以下內容不一致的操作示例

1
2
3
4
5
6
7
8
9
10
11
[[email protected] ~]$ ssh node2 'cat /etc/corosync/corosync.conf' | diff - /etc/corosync/corosync.conf
Enter passphrase for key '/home/flying/.ssh/id_rsa':
5c5
< transport: udpu1
---
> transport: udpu
#命令執行返回1,表示失敗
[[email protected] ~]$ echo $?
1
[[email protected] ~]$

References

Bibliography

Change Logs

  • 2016.02.02 10:25 Tue Asia/Beijing
    • 初稿完成
  • 2017.02.14 16:56 Tue Asia/Shanghai
    • 內容重構