23.ssh協議及實現(openssh)

SSH協議

  • ssh: secure shell, protocol, 22/tcp, 安全的遠程登錄
  • 具體的軟件實現:
    OpenSSH: ssh協議的開源實現,CentOS默認安裝
    dropbear:另一個開源實現
  • SSH協議版本
    v1: 基於CRC-32做MAC,不安全;man-in-middle
    v2:雙方主機協議選擇安全的MAC方式
    基於DH算法做密鑰交換,基於RSA或DSA實現身份認證
  • 兩種方式的用戶登錄認證:
    基於password
    基於key

Openssh軟件組成

  • OpenSSH介紹
  • 相關包3個:
    openssh :通用文件包
    openssh-clients :客戶端,可執行文件一般在bin下
    openssh-server :服務器端,可執行文件一般在sbin下,後面帶字母d
  • 工具:
    基於C/S結構
    Linux Client: ssh, scp, sftp,slogin
    Windows Client:xshell, putty, securecrt, sshsecureshellclient
    Server: sshd

ssh客戶端

  • 客戶端組件:
    ssh, 配置文件:/etc/ssh/ssh_config
    Host PATTERN
    StrictHostKeyChecking no 首次登錄不顯示檢查提示,相當於直接輸入yes,並自動下載對方公鑰到konw_hosts文件中。
  • 格式:
    ssh [user@]host [COMMAND] :鏈接特定用戶,不寫的話默認爲root,命令不寫的話默認會交互式執行,寫上的話就會執行然後退回到本機而不是留在連接狀態。
    ssh [-l user] host [COMMAND]
  • 常見選項
    -p port:遠程服務器監聽的端口
    -b:指定連接的源IP
    -v:調試模式
    -C:壓縮方式 :網速較慢時可壓縮一下數據方式進行連接
    -X:支持x11轉發
    -t:強制僞tty分配
    ssh -t remoteserver1 ssh -t remoteserver2 ssh remoteserver3

  • 允許實現對遠程系統經驗證地加密安全訪問
  • 當用戶遠程連接ssh服務器時,會複製ssh服務器端的/etc/ssh/ssh_host*key.pub(CentOS7默認是ssh_host_ecdsa_key.pub)文件中的公鑰到客戶機的~./ssh/know_hosts中。下次連接時,會自動匹配相應私鑰,不能匹配,將拒絕連接

注意點1:

  1. 如果利用ssh協議進行遠程登錄時是第一次登錄到對方的主機上,會提示一個“指紋”驗證信息在終端上,讓你輸入yes/no繼續下一步。

    • 這個指紋就是對方主機的/etc/ssh/ssh_host*key.pub(CentOS6和7默認都是ssh_host_rsa_key.pub)中的公鑰信息進行了sha256算法和MD5算法單向散列之後的值,可以被看做是對方主機的唯一標識。
    • 這個主要的目的就是爲了確認要連接的IP的主機是否是真正你想要連接的IP的主機(中途可能被截獲此連接請求),從而保證連接無誤,增強安全性不會連接到***的主機上去。
    • 第一次ssh連接成功之後,本機就會把對方主機的公鑰信息(注意是公鑰信息不是指紋信息)存儲到本地的~./ssh/know_hosts文件中(如果沒有這個文件會自動生成),等到下次再次連接相同IP的對方主機時,便會計算並將指紋信息自動進行比對(此時也就不會再出現詢問yes/no的選項了)。此時如果指紋比對相同一致會進行下一步的驗證,如果不同則ssh協議認爲對方主機被更換,便會自動斷開連接請求拒絕連接,以實現安全連接的目的。
    • 如果對方重裝了系統需要再次連接則可以把know_hosts中相對應的IP和公鑰給刪除掉即可,下次就會重新再次詢問yes/no並下載對方的公鑰信息了
  2. 從1中可知/etc/ssh文件夾下的公私鑰對信息很重要(尤其是私鑰,因爲公鑰是從私鑰計算出來的),如果私鑰被偷走則安全性就無法保證,因爲這樣就可以冒充對方的主機了。
  3. /etc/ssh文件夾下有客戶端和服務器端的配置文件(ssh和sshd)- 其中客戶端配置文件中這一項比較有用就是StrictHostKeyChecking ask 改爲 no ,讓它首次登錄不顯示檢查指紋的提示,相當於直接輸入yes,並自動下載對方公鑰到konw_hosts文件中。
    • 客戶端配置文件還有一項就是port 22,生產中爲了安全會把服務器端口給修改爲其它端口,因此每次鏈接的時候輸入命令要加上 ssh IP -p PORT的-p和端口選項。如果把客戶端配置文件這裏直接改爲服務器端口就可以省略手寫-p加端口選項了。
  4. ssh客戶端連接選項中的-X選項解釋:首先因爲圖形界面也是一個軟件(服務器端和客戶端),客戶端發送請求,則服務器端會顯示出圖形畫面並將客戶端的各種操作(鼠標,點擊等)進行事實的顯示出來,這就是X11協議等簡單工作原理介紹。
    • 顯示這個圖形界面的一方就是服務器,而進行操作的一方就是客戶端。圖形界面並非一定要在同一臺機器上既當做客戶端又當做服務器端。
    • 在這裏使用-X選項就能把SSH連接之後進行的操作(相當於圖形界面的客戶端操作,因爲ssh連接之後的操作其實是在對方的機器上進行的)的命令轉發到本機上,本機當做圖形界面的服務器端進行顯示。
    • 這裏需要注意本機是SSH的客戶端,圖形X11服務的服務器端;對方是SSH的服務器端,並且是圖形服務的客戶端。
    • 如果是利用的Xshell軟件先連接到linux機器上,然後再連接另一臺linux主機,利用-X選項,此時相當於進行了二次轉發,將本機windows的Xshell軟件當做圖形的服務器端進行了圖形的顯示。(Xshell默認有X11的服務器軟件,很方便)
  5. 在某些情況下是需要圖形界面環境的,因此4中的這個命令還是有很大的用處的。Xshell還可直接把整個linux的圖形界面給抓取到windows界面中。

    • 打開xstart,然後寫入session ,連接的IP地址,鏈接方式(密碼或者是key),然後選擇gnome方式連接即可,運行run
    • 退出的時候在窗口的上欄中選擇logout命令即可。
  6. SSH客戶端的-t選項是爲了解決多臺機器的跳板連接的問題的(最終想要連接的主機不可直連,但是可以通過前面多個主機的SSH跳轉連接最終連接到想要連接的主機上)
    • ssh -t remoteserver1 ssh -t remoteserver2 ssh remoteserver3 :注意最後的ssh後面不需要-t

公鑰交換

image

客戶端發起鏈接請求
服務端返回自己的公鑰,以及一個會話ID(這一步客戶端得到服務端公鑰)
客戶端生成密鑰對
客戶端用自己的公鑰異或會話ID,計算出一個值Res,並用服務端的公鑰加密
客戶端發送加密後的值到服務端,服務端用私鑰解密,得到Res
服務端用解密後的值Res異或會話ID,計算出客戶端的公鑰(這一步服務端得到客戶端公鑰)
最終:雙方各自持有三個祕鑰,分別爲自己的一對公、私鑰,以及對方的公鑰,
之後的所有通訊都會被加密,參看下面的圖片

SSH實現加密通訊

image

ssh服務登錄驗證

ssh服務登錄驗證方式

  1. 用戶/口令
  2. 基於密鑰

1.基於用戶和口令登錄驗證

  1. 客戶端發起ssh請求,服務器會把自己的公鑰發送給用戶(參考上面的交換公鑰的過程,最總雙方都有對方的公鑰)
  2. 用戶會根據服務器發來的公鑰對密碼進行加密
  3. 加密後的信息回傳給服務器,服務器用自己的私鑰解密,如果密碼正確,則用戶登錄成功

image

2.ssh服務基於密鑰登錄驗證

  1. 首先在客戶端生成一對密鑰(ssh-keygen)
  2. 並將客戶端的公鑰ssh-copy-id 拷貝到服務端
  3. 當客戶端再次發送一個連接請求,包括ip、用戶名
  4. 服務端得到客戶端的請求後,會到authorized_keys中查找,如果有響應的IP和用戶,就會隨機生成一個字符串,例如:magedu
  5. 服務端將使用客戶端拷貝過來的公鑰進行加密,然後發送給客戶端
  6. 得到服務端發來的消息後,客戶端會使用私鑰進行解密,然後將解密後的字符串發送給服務端
  7. 服務端接受到客戶端發來的字符串後,跟之前的字符串進行對比,如果一致,就允許免密碼登錄

image

基於key認證實現過程

  1. 在客戶端生成密鑰對
    ssh-keygen -t rsa [-P ''] [-f “~/.ssh/id_rsa"]
  2. 把公鑰文件傳輸至遠程服務器對應用戶的家目錄
    ssh-copy-id [-i [identity_file]] [user@]host
  3. 測試
  4. 在SecureCRT或Xshell實現基於key驗證
    在SecureCRT工具—>創建公鑰—>生成Identity.pub文件
    轉化爲openssh兼容格式(適合SecureCRT,Xshell不需要轉化格式),並複製到需登錄主機上相應文件authorized_keys中
    注意權限必須爲600,在需登錄的ssh主機上執行:ssh-keygen -i -f Identity.pub >> .ssh/authorized_keys
  5. 重設私鑰口令:
    ssh-keygen –p
  6. 驗證代理(authentication agent)保密解密後的密鑰
    這樣口令就只需要輸入一次
    在GNOME中,代理被自動提供給root用戶
    否則運行ssh-agent bash
  7. 鑰匙通過命令添加給代理
    ssh-add

注意點2:

  1. 注意了基於KEY驗證的方式的公鑰私鑰對和SSH傳輸數據過程中的公鑰私鑰對是不同的。前者就是爲了登錄驗證所用,存放在~/.ssh文件夾中,後者是爲了雙方數據傳輸的安全性,在第一次連接時會進行交換公鑰,它存放在/etc/ssh文件夾下(有不同算法的許多公鑰私鑰對)。
  2. ssh-keygen生成時直接回車即可,默認rsa,然後可以輸入密碼對這個生成的公私鑰對的私鑰進行加密,生成的公私鑰對默認存放在當前用戶的~/.ssh/id_rsa文件中(也可以修改到其他地方,這樣的話拷貝的時候要-i指定文件).
    • 之後拷貝的時候也是把它拷貝到對方的對應用戶的家目錄下的.ssh文件夾中並更名爲authorized_keys,就類似於knows_hosts文件,裏面每一項就是一個公鑰。
    • 拷貝的時候最好用ssh-copy-id 用戶@hostIP 命令,它會自動創建.ssh目錄以及authorized文件並拷貝過去,並將文件裏的格式寫好。(同時如果用-i命令指定本機拷貝的文件爲私鑰文件,它會自動拷貝的也是公鑰文件,不用擔心拷貝錯誤)。
    • 注意拷貝到哪個用戶的家目錄下,就只能連接這個用戶,其他的用戶仍舊不能連接。不過此時直接可以在遠程要連接的主機上cp到其他用戶的家目錄下即可。不寫用戶時默認拷貝到root家目錄下
    • 注意如果用命令拷貝的沒有問題,但是如果自己手創建的.ssh文件夾和autuorized_keys文件要注意文件夾和文件的權限問題,這裏面.ssh文件夾的權限是700,autho文件的權限是600.所屬主所屬組都是對應用戶和它的組
      2.2 注意ssh-keygen命令默認生成的key如果再次執行這個命令會把原先的key的文件給覆蓋掉(名字一樣的話),而ssh-copy-id命令拷貝key到遠程主機上不會覆蓋掉遠程主機上的authorized文件,而是追加本機的公鑰到文件中(因此多個主機均可以連接同一臺機器)。一定要注意的就是客戶端私鑰文件一定要放在對應用戶的.ssh文件夾中。
  3. 注意基於Key驗證的SSH登陸,就算更改了拷貝了KEY的主機的用戶的密碼也不會影響SSH的遠程登錄。因此一定要保證連接控制端的私鑰不能丟,不然極度不安全,如果它被偷走並放入其他機器中的.ssh中,它也能連接導入key的主機了!因此最好加上密碼:(私鑰文件的默認權限也是600)
    • 可以在生成私鑰的時候非交互式-N(腳本常用)指定密碼:
      ssh-keygen -N 'PASSWORD'
    • 也可以生成私鑰的時候交互式輸入密碼
    • 還有就是如果生成的時候沒有加密碼,則生成之後可用ssh-keygen -p 選項交互式修改密碼(也可以再加上-P -N -f 3個參數並寫好對應的舊密碼新密碼和指定文件來非交互式 修改密碼)
  4. 加完口令之後,每次連接ssh服務的時候就會讓自己輸入口令,不過這次輸入的口令是本機私鑰文件的口令而非對方用戶賬戶的口令。但這樣就實現不了便捷連接的目的了,因此可以通過代理的方式:

    • ssh-agent bash 開啓代理,這個命令其實開啓了一個子bash並把它當做代理
    • ssh-add 輸入口令添加到新開的bash中,這樣再連接就不需要口令了
      通過代理的方式就實現了安全以及便捷的目的了(雖然每次開啓shell仍然需要一次口令,不過安全性大大提高),不過一旦退出這個子bash shell,則代理就會失效
  5. Xshell中也可以利用KEY驗證來登錄linux中:

    • 在tools中打開新建用戶密鑰嚮導,然後生成密鑰
    • 生成密鑰之後查看它並將裏面的公鑰文件Save as a file到windows中
    • 然後將這個公鑰文件導入到需要連接的linux主機中,並追加重定向到authorized_keys文件中(注意在root家目錄下)
    • 新建連接並選擇root用戶連接,用KEY驗證的方式。此時便可以連接了。
  6. 如果在一個集羣環境中想要所有的機器都能互相連接(或者說某些機器能夠連接其他所有機器),只需要把公私鑰和authorized_keys這三個文件同時拷貝到所有主機上的.ssh文件中(拷貝到需要連接所有主機的機器上,只能被連接的主機只拷貝authorized文件)即可。

    • 簡單點的做法就是生成公私鑰對之後,先用ssh-copy-id命令拷貝到自己機器上(生成authorize),然後把ssh整個目錄拷貝到需要連接並控制其他機器的主機上即可。
  7. scp命令不僅可以雙方互拷貝,還能夠控制別的兩臺機器之間向互拷貝(先做好KEY驗證或者說知道用戶密碼)**
  8. scp命令默認和cp命令一樣,拷貝的時候直接覆蓋(cp -i可以詢問,scp沒有)。同時它還有一個缺點就是不能夠實現只拷貝修改過的文件(沒有類似cp -u的命令)。因此可以用rsync命令代替它彌補這個缺點
    • rsync和scp的用法基本上一致(也類似cp),不過它的好處就是默認只拷貝變化過的文件(雖然也是直接覆蓋),與scp相比能夠減少帶寬,只拷貝需要拷貝的文件。
    • 因此可用它用來實現服務器之間的數據相互同步(實現備份),(當然相互更改也可以,此時沒有主從備份之分),並且能夠使用更少的帶寬。
    • 需要注意的就是它拷貝目錄的時候後面加上/和不加/分別代表拷目錄下文件和目錄本身,這點和scp和cp都不相同。(但要注意其它的問題比如目錄存在不存在的不同情況,詳細查看cp命令的表格)

其他一些命令:

scp命令

  • scp [options] SRC... DEST/
  • 兩種方式:
    scp [options] [user@]host:/sourcefile /destpath
    scp [options] /sourcefile [user@]host:/destpath
  • 常用選項:
    -C 壓縮數據流
    -r 遞歸複製
    -p 保持原文件的屬性信息
    -q 靜默模式
    -P PORT 指明remote host的監聽的端口(默認也是受ssh_config控制)

rsync命令

基於ssh和rsh服務實現高效率的遠程系統之間複製文件
使用安全的shell連接做爲傳輸方式
rsync -av /etc server1:/tmp 複製目錄和目錄下文件
rsync -av /etc/ server1:/tmp 只複製目錄下文件
比scp更快,只複製不同的文件

  • 常用選項:
    -n 模擬複製過程
    -v 顯示詳細過程
    -r 遞歸複製目錄樹
    -p 保留權限
    -t 保留時間戳
    -g 保留組信息
    -o 保留所有者信息
    -l 將軟鏈接文件本身進行復制(默認)
    -L 將軟鏈接文件指向的文件複製
    -a 存檔,相當於–rlptgoD,但不保留ACL(-A)和SELinux屬性(-X)

sftp命令(幾乎不用)

交互式文件傳輸工具
用法和傳統的ftp工具相似
利用ssh服務實現安全的文件上傳和下載
使用ls cd mkdir rmdir pwd get put等指令,可用?或help獲取幫助信息
sftp [user@]host
sftp> help

輕量級自動化運維工具

  • pssh:基於python編寫,可在多臺服務器上執行命令的工具,也可實現文件複製,提供了基於ssh和scp的多個並行工具
    項目:http://code.google.com/p/parallel-ssh/
  • pdsh:Parallel remote shell program,是一個多線程遠程shell客戶端,可以並行執行多個遠程主機上的命令。 pdsh可以使用幾種不同的遠程shell服務,包括標準的“rsh” ,Kerberos IV和ssh
    項目: https://pdsh.googlecode.com/
  • mussh:Multihost SSH wrapper,是一個shell腳本,允許您使用一個命令在多個主機上通過ssh執行命令或腳本。 mussh可使用ssh-agent和RSA / DSA密鑰,以減少輸入密碼
    項目:http://www.sourceforge.net/projects/mussh

說明:以上工具都包含在EPEL源中
yum install pssh

PSSH工具

選項如下:
--version:查看版本
-h:主機文件列表,內容格式爲” [user@]host[:port]”
-H:主機字符串,內容格式爲” [user@]host[:port]”
-A:手動輸入密碼模式
-i:每個服務器內部處理信息輸出
-l:登錄使用的用戶名
-p:併發的線程數【可選】
-o:輸出的文件目錄【可選】,此項會讓對方主機執行命令的結果輸出到本機的-o後面指定的目錄中,創建兩個對方HOST名的文件來保存。
-e:錯誤輸出文件【可選】
-t:TIMEOUT 超時時間設置,0無限制【可選】
-O:SSH的選項
-P:打印出服務器返回信息
-v:詳細模式

pssh示例

  • 通過pssh批量關閉seLinux
    pssh -H [email protected] -i ‘sed -i "s/^SELINUX=.*/SELINUX=disabled/" /etc/selinux/config’
  • 批量發送指令
    pssh -H [email protected] -i setenforce 0
    pssh -H [email protected] -i hostname
  • 當不支持ssh的key認證時,通過 -A選項,使用密碼認證批量執行指令
    pssh -H [email protected] -A -i hostname
  • 將標準錯誤和標準正確重定向都保存至/app目錄下
    pssh -H 192.168.1.10 -o /app -e /app -i “hostname”

pscp.pssh命令

  • pscp.pssh功能是將本地文件批量複製到遠程主機
    pscp [-vAr] [-h hosts_file] [-H [user@]host[:port]] [-l user] [-p par] [-o outdir] [-e errdir] [-t timeout] [-O options] [-x args] [-X arg] local remote
  • pscp-pssh選項
    -v 顯示覆制過程
    -r 遞歸複製目錄
  • 將本地curl.sh 複製到/app/目錄
    pscp.pssh -H 192.168.1.10 /root/test/curl.sh /app/
    pscp.pssh -h host.txt /root/test/curl.sh /app/
  • 將本地多個文件批量複製到/app/目錄
    pscp.pssh -H 192.168.1.10 /root/f1.sh /root/f2.sh /app/
  • 將本地目錄批量複製到/app/目錄
    pscp.pssh -H 192.168.1.10 -r /root/test/ /app/

pslurp命令

  • pslurp功能是將遠程主機的文件批量複製到本地
    pslurp [-vAr] [-h hosts_file] [-H [user@]host[:port]] [-l user] [-p par][-ooutdir] [-e errdir] [-t timeout] [-O options] [-x args] [-X arg] [-L localdir] remote local(本地名)
  • pslurp選項
    -L 指定從遠程主機下載到本機的存儲的目錄,local是下載到本地後的名稱
    -r 遞歸複製目錄
  • 批量下載目標服務器的passwd文件至/app下,並更名爲user
    pslurp -H 192.168.1.10 -L /app /etc/passwd user

注意點3:

  1. pssh可以實現小型化的自動化運維操作,利用-H選項的時候有兩種方式
    • pssh -H HOST1 -H HOST2 CMD
    • pssh -H “HOST1 HOST2 ...” CMD
  2. 它利用的驗證方式和ssh是一樣的,可以基於key驗證和密碼驗證。
    • 基於密碼驗證的時候要加上-A選項,此時它會變成交互式方式讓用戶輸入密碼。但是注意僅能輸入一次密碼,因此如果被控制的主機的密碼不相同則無法實現全部控制並操作的效果。
  3. 利用-i選項可以看到被操作的主機上的命令的結果的輸出(標準輸出或者錯誤),不過注意一定要把pssh的各種選項放在前面,最後一項再寫上要在被控制的主機上的CMD命令
    • Usage: pssh [OPTIONS] command [...]
  4. 同時經過測試得知最後一項只能寫一個命令,如果寫的更多的只能被當做這個命令的參數來使用。就算加上單引號或者雙引號把命令分隔開也無效(就算加上還是會被當做命令以及命令的參數)
  5. 更加方便操作管理的方式是利用-h HOSTfile的方式來執行,其中HOSTfile中的每一行就是一個要被控制的主機IP地址
  6. 特別注意點:注意不論是ssh還是pssh不指定用戶名的時候,都是會以當前在控制端(也就是本機)登陸的用戶名爲默認登陸用戶名(也就是把它當做HOST前@前面寫的用戶名)來進行遠程主機的相同的用戶名進行登陸連接。
  7. 還有就是執行命令的時候如果需要對方主機的變量,以及使用通配符等,則需要用單引號(雙引號無效)引起來纔可,不然會當做爲本機的變量給解釋並使用了,比如說
    • pssh -H 192.168.36.103 -H 192.168.36.144 -i echo '$HOSTNAME'
      :$HOSTNAME必須單引號引起來,當然也可以把整個CMD命令 'echo $HOSTNAME'引起來
    • pssh -H 192.168.36.103 -H 192.168.36.144 -i 'rm -rf /data/* '
      : *這裏如果不用單引號引起來rm命令,則會把/data/ 中的通配符解釋爲本機的/data/下的所有非隱藏文件而不是對方主機上的,需要注意**
  8. pscp.pssh 只能把本地的文件批量複製到遠程主機上,注意可以一次性複製多個(或者目錄,別忘了加-r),但是要注意要把目標端寫在最後面,要複製的文件或者目錄(可以多個)寫在中間,最前面寫選項:Usage: pscp.pssh [OPTIONS] local remote
  9. 而把遠程主機上的文件複製到本機上的命令爲pslurp命令,注意它的選項也是寫在最前面(-h file -L localdir 中-h -L都是選項,只不過有參數而已),然後寫上遠程的要複製的文件或者目錄,最後可以寫上想要被改名的名字:
    • Example: pslurp -h hosts.txt -L /tmp/outdir -l irb2 /home/irb2/foo.txt foo.txt
    • 此命令就是把hosts.txt中的主機下,以irb2的用戶連接它們並將它的家目錄下的foo.txt文件複製到本機的outdir文件夾中並改名爲foo.txt。 此命令會在本機-L後面的文件夾中創建hosts中對應主機名字的文件夾並將被複制的文件放入進去。

簡單測試用(可用它配合命令修改selinux,也可直接用pscp.pssh拷貝本機selinux配置文件覆蓋遠程端的配置文件):

20:17[root@centos7 ~]# pssh -H 192.168.36.103 -H 192.168.36.144 -A -i hostname 
Warning: do not enter your password if anyone else has superuser
privileges or access to your account.
Password: 
[1] 20:17:21 [SUCCESS] 192.168.36.103
Centos6.10Test
[2] 20:17:21 [SUCCESS] 192.168.36.144
centos7.6test
20:17[root@centos7 ~]# pssh -H 192.168.36.103 -H 192.168.36.144 -i hostname 
[1] 20:17:26 [SUCCESS] 192.168.36.103
Centos6.10Test
[2] 20:17:26 [SUCCESS] 192.168.36.144
centos7.6test
20:17[root@centos7 ~]# pssh -H 192.168.36.103 -H 192.168.36.144  hostname 
[1] 20:17:31 [SUCCESS] 192.168.36.103
[2] 20:17:31 [SUCCESS] 192.168.36.144
20:17[root@centos7 ~]# 

20:38[root@centos7 ~]# pssh -H 192.168.36.103 -H 192.168.36.144 -i echo $HOSTNAME
[1] 20:43:24 [SUCCESS] 192.168.36.103
centos7.6test
[2] 20:43:24 [SUCCESS] 192.168.36.144
centos7.6test
20:43[root@centos7 ~]# pssh -H 192.168.36.103 -H 192.168.36.144 -i echo '$HOSTNAME'
[1] 20:43:30 [SUCCESS] 192.168.36.103
nihao
[2] 20:43:30 [SUCCESS] 192.168.36.144
nihao

批量複製本機文件到對方並且改名
21:11[root@centos7 ~]# pscp.pssh -H 192.168.36.103 -H 192.168.36.144 /etc/fstab /data/fstabpscptest
[1] 21:16:16 [SUCCESS] 192.168.36.103
[2] 21:16:16 [SUCCESS] 192.168.36.144

再複製回來,經過測試得知必須嚴格按照下面的格式纔可。
Example: pslurp -h hosts.txt -L /tmp/outdir -l irb2 /home/irb2/foo.txt foo.txt

21:19[root@centos7 ~]# pslurp -H 192.168.36.103 -H 192.168.36.144  -L /data/ /data/fstabpscptest fstabtestpul
[1] 21:19:48 [SUCCESS] 192.168.36.103
[2] 21:19:48 [SUCCESS] 192.168.36.144
21:19[root@centos7 ~]# cd /data
21:20[root@centos7 /data]# ls 192.*
192.168.36.103:
fstabtestpul

192.168.36.144:
fstabtestpul

SSH端口轉發

  • SSH端口轉發
    SSH 會自動加密和解密所有 SSH 客戶端與服務端之間的網絡數據。但是,SSH 還能夠將其他 TCP 端口的網絡數據通過 SSH 鏈接來轉發,並且自動提供了相應的加密及解密服務。這一過程也被叫做“隧道”(tunneling),這是因爲SSH 爲其他 TCP 鏈接提供了一個安全的通道來進行傳輸而得名。例如,Telnet,SMTP,LDAP 這些 TCP 應用均能夠從中得益,避免了用戶名,密碼以及隱私信息的明文傳輸。而與此同時,如果工作環境中的防火牆限制了一些網絡端口的使用,但是允許 SSH 的連接,也能夠通過將 TCP 端口轉發來使用 SSH 進行通訊

SSH 端口轉發能夠提供兩大功能:

加密 SSH Client 端至 SSH Server 端之間的通訊數據
突破防火牆的限制完成一些之前無法建立的 TCP 連接

SSH端口轉發

本地轉發:

-L localport:remotehost:remotehostport sshserver

  • 選項:
    -f 後臺啓用
    -N 不打開遠程shell,處於等待狀態
    -g 啓用網關功能
  • 示例
    ssh –L 9527:telnetsrv:23 -Nfg sshsrv :開啓本地端口轉發
    telnet 127.0.0.1 9527 :連接本地的端口9527(這個命令就相當於連接到了
    當訪問本機的9527的端口時,被加密後通過SSH隧道轉發到sshsrv的ssh服務,再解密被轉發到telnetsrv:23
    data <--> ocalhost:9527(本地SSH轉發端口,自定義的轉發端口) <--> localhost:XXXXX(本地作爲SSH客戶端,發送的隨機端口) <--> sshsrv:22(對方作爲SSH服務器,接收端口) <--> sshsrv:YYYYY(對方作爲telnet客戶端,發送的隨機端口) <--> telnetsrv:23(最終連接的主機telnet服務器,接收端口)

遠程轉發:

-R sshserverport:remotehost:remotehostport sshserver

  • 示例:
    ssh –R 9527:telnetsrv:23 –Nf sshsrv
    讓sshsrv偵聽9527端口的訪問,如有訪問,就加密後通過ssh服務轉發請求到本機ssh客戶端,再由本機解密後轉發到telnetsrv:23
    Data <--> sshsrv:9527 <--> sshsrv:22 <--> localhost:XXXXX <--> localhost:YYYYY <--> telnetsrv:23

動態端口轉發:

當用firefox訪問internet時,本機的1080端口做爲代理服務器,firefox的訪問請求被轉發到sshserver上,由sshserver替之訪問internet
ssh -D 1080 root@sshserver -fNg
在本機firefox設置代理socket proxy:127.0.0.1:1080
curl --socks5 127.0.0.1:1080 http://www.google.com

X 協議轉發

  • 所有圖形化應用程序都是X客戶程序
    能夠通過tcp/ip連接遠程X服務器
    數據沒有加密機,但是它通過ssh連接隧道安全進行
  • ssh -X user@remotehost gedit
    remotehost主機上的gedit工具,將會顯示在本機的X服務器上
    傳輸的數據將通過ssh連接加密

協議轉發注意點:

  1. Xshell命令中可以直接打開gnome命令,只不過centos6和7不同而已。並不一定需要xstart,看下面的2中。
  2. 可以用ps aux | grep gnome 查看已經打開的進程來判斷 gnome的打開命令,同時可以gnome-session --help查看幫助:
    • 6:/usr/bin/gnome-session --display $DISPLAY
    • 7:/usr/bin/gnome-session --session gnome-classic
  3. 如果在Xshell中無法拉取gedit等圖形窗口,可以查看是否在對方主機的sshd_config中開啓了兩個轉發的功能(詳細看下面)
  4. 注意-X 選項可以換成 -Y 試試效果
  5. 如果兩臺主機都是linux主機,則需要另外的方法抓取,這裏說的是利用windows的Xmanager來抓取linux的桌面以及圖形工具的界面(當然也可以先利用Xshell連接到一臺linux主機上,然後再次SSH連接到另外一臺主機,然後利用genome,gedit等命令打開這個二次連接的主機上的圖形界面)
檢查是否安裝xterm和xrog
[root@localhost bin]# rpm -qa|grep xorg-x11-xauth -y
xorg-x11-xauth-1.0.9-1.el6.x86_64
[root@localhost bin]# rpm -qa|grep xterm
xterm-253-1.el6.x86_64
檢查是否安裝了圖形化界面
[root@localhost bin]# more /etc/inittab
id:5:initdefault:
到底應該可以確定sshd禁止了x11Forwarding功能呢個
修改文件
[root@localhost ~]# vi /etc/ssh/sshd_config
AllowTcpForwarding yes
X11Forwarding yes
重啓sshd服務

注意點4:

  1. 本地開啓SSH端口轉發之後的數據傳輸過程詳細看上面所寫,需要注意的是本機一定要能夠利用openssh連接到中間的一個用於轉發(跳板)的機器的SSH服務纔可,不能夠被防火牆等安全策略阻隔(基於密碼或者key都行)
    -L localport:remotehost:remotehostport sshserver [-p port]
    • 注意-L 只是一個選項而已,後面跟的都是參數,目的就是爲了開啓通道,其他的用法和ssh的用法相同。
    • localport就是本機要利用的轉發到跳板機上的端口,一定要找一個沒有使用的端口
    • 其中remotehost就是最終要連接的主機IP(或者配置了DNS之後的可解析域名)
    • remotehostport就是對應的最終連接主機要連接的端口,此端口一定要與接來下需要經過這個端口轉發的命令服務想對應。比如如果這裏寫的是23,那麼下面要進行的本機客戶端命令肯定就是telnet,不能寫其他的(除非自定義了端口)
    • 最後的sshserver就是中間的可以被SSH協議直接相連的轉發機(跳板機),可寫IP或者域名(要配置DNS)
    • 附加知識點:ssh服務可以連接本機localhost(用命令ssh localhost,本機即當客戶端又當服務端,同時因爲hosts文件中寫的有解析),因爲ssh服務默認監聽任何IP。(可用ss -ntlp查看)
    • 最後加上-fN選項讓它建立隧道並且後臺執行不登錄,需要關閉的時候殺掉此進程即可。
  2. SSH轉發的過程中會對數據進行加密,但是telnet不會,不過因爲在企業內網中,所以也不用特別擔心安全問題。(注意安裝telnet和telnet-server包,以及6中如果做服務器開啓xinetd監控)
  3. 不過實際應用中基本上都是有防火牆配置,因此要在防火牆內部建立向外連接的SSH轉發,此時用的是-R選項
    -R sshserverport:remotehost:remotehostport sshserver
    在這裏和-L 的區別就是把sshserver和ssh客戶端相互交換了,在命令的區別就是隻有sshserver不同而已:
    • -L 選項是在遠程機器上操作,那幾項都很好理解上面也已經解釋,其中此時的sshserver是跳板機的地址
    • -R 選項則是在跳板機上操作,中間的選項和-L的一模一樣,惟一的區別就是sshserver換成了-L選項操作時的機器的IP
    • 最終實現的效果和-L一模一樣,只不過跳過了防火牆的限制。可以先按照-L的思想去想然後再按照-R來寫。
  4. 前面兩種都是單一的只能讓跳板機連接到最終端主機的的特定服務和特定端口,但是動態端口轉發可讓跳板機用於訪問它能夠連接到的任何主機的任何端口(訪問外網)。
    ssh -D localport root@sshserver -fN
    • 注意此選項如果不加-g選項時,是在本機執行的(和-L相同,在本地本機執行),此時需要本機以及跳板機兩臺機器,這個跳板機可以連接它能連接到的任何機器並將數據轉發回來。
    • 不過此時這個跳板機只能接收執行上面的這個命令的主機進行轉發和訪問(因爲22端口只開啓了監聽執行上面命令的IP,而不是*監聽所有的端口)。可以用ss -ntl查看便知。
    • 當然利用瀏覽器訪問時要設置瀏覽器代理(sockets host)的IP及端口爲127.0.0.1 localport(本機IP和本機端口)
    • 此命令不能用其他機器利用跳板機進行訪問了(想要訪問每臺機器都要執行上面的命令),而且只限定了能夠執行上面命令的linux機器才能(windows無法執行此命令)
      ssh -D localport root@sshserver(localhost) -fNg
    • 注意此命令加了-g之後,執行命令的機器是跳板機上,(相當於把上個命令中的本地機和跳板機合二爲一)
    • 執行之前要現在sshd_config服務端配置文件中修改GATEWAYPorts 爲yes ,然後再執行上面的命令,其中中間的主機就是本機的IP,可以直接寫localhost.
    • 此時再用ss -ntl命令就可看到22端口前面的IP不是綁定爲單一IP,而是任意IP的符號*了。這樣就可以用其他任何機器利用此轉發服務器機進行訪問了(包括windos系統,不過也是要在瀏覽器中配置代理)
  5. 注意還有一種可能就是兩臺機器按照4中第一種的配置來配置,然後其他的機器通過這個配置中的控制端來兩次轉發,實現控制企業業內的機器的效果。
    • 此時4中第一種的配置的命令中,也要開啓路由配置以及-g選項,把這個防火牆外的控制端主機作爲防火牆外的跳板機,防火牆內的服務器作爲防火牆內的跳板機(兩個跳板機),然後再用其他的機器連接防火牆外的這個控制端跳板到防火牆內的服務器跳板,然後再連接防火牆內的其他機器。
  6. 5中不常用,最常用的就是直接用另外的機器先ssh連接到這個防火牆外的機器上,然後再次ssh連接到防火牆內的跳板機(這個跳板機只允許防火牆外的那個跳板機連接,可以配置),然後再控制防火牆內的其他主機。

本地轉發測試示例(注意telnet服務受到PAM控制默認不能root遠程登陸):

提前在最終的目標端配置好telnet-server服務,跳板轉發端配置好telnet客戶端以及ssh的服務端,本機配置好telnet的客戶端(要連接端口用)
ss -na |grep 9696 :查看9696端口是否被佔用
ssh -L 9696:192.168.36.103:23 192.168.36.144 -fN
telnet 127.0.0.1 192.168.36.103 -l zhang

最後利用ps aux | grep ssh ,然後kill PID 殺掉這個後臺進程即可,不過在此之前查看:
注意下面的192.168.36.1是windows的IP,本機地址爲102,跳板機爲144,最終要連接到爲103
本機查看ss -nt
ESTAB      0      0                                       127.0.0.1:60948                                               127.0.0.1:9696               
ESTAB      0      0                                  192.168.36.102:50902                                          192.168.36.144:22                 
ESTAB      0      0                                       127.0.0.1:9696                                                127.0.0.1:60948              
ESTAB      0      52                                 192.168.36.102:22                                               192.168.36.1:2109               
ESTAB      0      0                                  192.168.36.102:22                                               192.168.36.1:8360    
跳板機查看ss -nt
ESTAB      0      0                                  192.168.36.144:43140                                          192.168.36.103:23                 
ESTAB      0      52                                 192.168.36.144:22                                               192.168.36.1:8362               
ESTAB      0      0                                  192.168.36.144:22                                             192.168.36.102:50902    
最終端機查看ss -nt
ESTAB      0      0                                               192.168.36.103:23                                             192.168.36.144:43140 
ESTAB      0      52                                              192.168.36.103:22                                               192.168.36.1:2107  

遠程轉發測試示例:

上面的操作隧道kill後,直接在跳板機上輸入
ssh -R 9696:192.168.36.103:23 192.168.36.102 -fN
既可以達到和上面一模一樣的效果,注意端口9696不是在跳板機上打開的
然後控制端輸入
telnet 127.0.0.1 192.168.36.103 -l zhang 
測試結果和上面也一樣,就是服務器和客戶端交換而已

本機開啓網關並動態端口轉發:

注意要在將要作爲sshd服務器(跳板機上)執行此命令
先在sshd_config文件中修改GATWAYports 爲yes,然後
ssh -D 9696 localhost(或者本機ip) -gfN
最後配置windows瀏覽器代理IP和端口指向這個機器和9696即可

ssh服務器

服務器端:sshd, 配置文件: /etc/ssh/sshd_config ,修改完別忘了重啓服務。更詳細查看man sshd_config
常用參數:

Port  : 此項修改作爲服務器端的端口號,默認22.注意修改之後Xshell別忘了改
ListenAddress ip :默認所有的IP 可以自己修改指定某些特定的IP鏈接,其他的不能連接
LoginGraceTime 2m :未認證連接狀態(也就是密碼沒輸入(或沒輸入正確)但是ssh並未斷開時)最大能持續時間,默認120秒。
PermitRootLogin yes : 是否允許SSH用root賬號登陸,ubantu默認就是不能登陸。可以改爲不允許,用普通用戶登陸之後再用su 或者 sudo 切換。更加安全(避免***暴力猜解root口令)
StrictModes yes :檢查.ssh/文件的所有者,權限等,如果不匹配則無法登陸
MaxAuthTries 6  :它的值的一半代表登陸時輸入的口令最大次數,超過這個輸入次數(輸錯)則連接斷開。
MaxSessions 10 : 同一個連接內,SSHD服務支持的連接最多會話數量。改爲1的話同一時間一臺連接的主機上只能打開一個session。 注意它指的是一個連接(相同IP相同端口號)內的會話(session)數量,而不是連接數量;它不影響本機再開一個端口(相同IP但是不同的端口號)再次建立一個SSH連接.
PubkeyAuthentication yes  :是否允許基於KEY驗證
PermitEmptyPasswords no   :是否允許空口令登陸(一個賬號沒有密碼,是否允許用這個賬號登錄)
PasswordAuthentication yes :是否允許基於賬號密碼登陸
GatewayPorts no  :是否允許當做網關端口,在SSHD端口轉發的時候開啓它,則監聽端口會變成所有IP,否則只能是本機的127.0.0.1端口。
ClientAliveInterval 10 :單位:秒 ,它表示客戶端連接之後沒有進行任何操作的檢測間隔,要配合下面的次數一起使用。
假如在這個間隔內沒有操作,則次數加1,然後進行下一輪的檢測。如果在下一輪這個間隔內仍然沒有操作,次數再次加一,直到達到下面規定的次數時,一直沒有操作則此時連接斷開。
但是如果這整個期間有任何一次操作,則檢測次數清零,重新開始檢測。
ClientAliveCountMax 0 :默認3 ,根據次數和間隔可以計算出客戶端無操作令SSH服務自動斷開的最大時間爲 :間隔時間*檢測次數

UseDNS yes : 是否允許DNS解析域名,不允許則只能輸入IP了,把它禁用可以優化SSH加快連接速度
GSSAPIAuthentication yes : 提高速度可改爲no 
MaxStartups :未認證連接(也就是連接上但是密碼未輸入,ssh也未斷開的狀態)最大值,默認值10
詳細看man幫助,它的寫法爲 10:30:100 ,表示10個最大的未認證連接狀態,然後就會以30%的比例丟棄連接,並隨着未認證連接數量的增多線性增長這個比例,直到達到100個未認證連接狀態的值,此時不能再有新的鏈接接入(丟棄率達到100%)
Banner /path/file  :登陸的提示信息,指定文件,類似於issue和motd

限制可登錄用戶的辦法:
AllowUsers user1 user2 user3
DenyUsers
AllowGroups
DenyGroups

AllowUsers
             This keyword can be followed by a list of user name patterns, separated by spaces.  If specified, login is allowed only for user
             names that match one of the patterns.  Only user names are valid; a numerical user ID is not recognized.  By default, login is
             allowed for all users.  If the pattern takes the form USER@HOST then USER and HOST are separately checked, restricting logins to par‐
             ticular users from particular hosts.  HOST criteria may additionally contain addresses to match in CIDR address/masklen format.  The
             allow/deny directives are processed in the following order: DenyUsers, AllowUsers, DenyGroups, and finally AllowGroups.  All of the
             specified user and group tests must succeed, before user is allowed to log in.

ssh端口轉發還有部分未寫完,暫時空在這裏,之後繼續補充

sshd服務的推薦配置和操作:注意一定要先改了之後再連接到互聯網中!

  1. 建議使用非默認端口
  2. 禁止使用protocol version 1
  3. 限制可登錄用戶
  4. 設定空閒會話超時時長
  5. 利用防火牆設置ssh訪問策略
  6. 僅監聽特定的IP地址
  7. 基於口令認證時,使用強密碼策略
    tr -dc A-Za-z0-9_ < /dev/urandom | head -c 12| xargs
    這裏xargs用於換行用的
  8. 使用基於密鑰的認證
  9. 禁止使用空密碼
  10. 禁止root用戶直接登錄
  11. 限制ssh的訪問頻度和併發在線數
  12. 經常分析日誌 tail -f /var/log/secure
    可利用這個日誌文件來判斷是否某些有***嫌疑的IP進行過濾

附加:ssh鏈接數設置問題

今天碰到一個問題,腳本執行scp文件拷貝,因爲拷貝的服務器很多,所以拷貝腳本的實現是在把拷貝動作轉後臺執行,結果發現一堆文件拷貝失敗。比較有迷惑性的是,拷貝失敗的通常是同一個文件夾拷貝到所有服務器時失敗,所以開頭查問題的方向是專門查該文件,後來發現了輸出終端的輸出錯誤:ssh_exchange_identification: Connection closed by remote host。
這裏的問題是ssh的連接數超出了服務器設置的上限,解決如下:
修改服務器上的這個文件:/etc/ssh/sshd_config,找到兩行:
MaxSessions:最大允許鏈接數,默認10.
MaxStartups:最大允許保持多少個未認證鏈接(未輸入登錄密碼),默認值是10.
把他們的數字改大,例如改成
MaxSessions 1000
MaxStartups 1000
最後重啓sshd service sshd restart,然後重新連接即可。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章