本文對SSH連接驗證機制進行了非常詳細的分析,還詳細介紹了ssh客戶端工具的各種功能,相信能讓各位對ssh有個全方位較透徹的瞭解,而不是僅僅只會用它來連接遠程主機。 另外,本人翻譯了ssh客戶端命令的man文檔,如本文有不理解的地方,可以參考man文檔手冊:ssh中文手冊。 本文目錄: 1.1 非對 ...
本文對SSH連接驗證機制進行了非常詳細的分析,還詳細介紹了ssh客戶端工具的各種功能,相信能讓各位對ssh有個全方位較透徹的瞭解,而不是僅僅只會用它來連接遠程主機。
另外,本人翻譯了ssh客戶端命令的man文檔,如本文有不理解的地方,可以參考man文檔手冊:ssh中文手冊。
本文目錄:
1.11.3 ssh安全隧道(三):動態埠轉發(SOCKS代理)
1.1 非對稱加密基礎知識
對稱加密:加密和解密使用一樣的演算法,只要解密時提供與加密時一致的密碼就可以完成解密。例如QQ登錄密碼,銀行卡密碼,只要保證密碼正確就可以。
非對稱加密:通過公鑰(public key)和私鑰(private key)來加密、解密。公鑰加密的內容可以使用私鑰解密,私鑰加密的內容可以使用公鑰解密。一般使用公鑰加密,私鑰解密,但並非絕對如此,例如CA簽署證書時就是使用自己的私鑰加密。在接下來介紹的SSH服務中,雖然一直建議分發公鑰,但也可以分發私鑰。
所以,如果A生成了(私鑰A,公鑰A),B生成了(私鑰B,公鑰B),那麼A和B之間的非對稱加密會話情形包括:
(1).A將自己的公鑰A分發給B,B拿著公鑰A將數據進行加密,並將加密的數據發送給A,A將使用自己的私鑰A解密數據。
(2).A將自己的公鑰A分發給B,並使用自己的私鑰A加密數據,然後B使用公鑰A解密數據。
(3).B將自己的公鑰B分發給A,A拿著公鑰B將數據進行加密,並將加密的數據發送給B,B將使用自己的私鑰B解密數據。
(4).B將自己的公鑰B分發給A,並使用自己的私鑰B加密數據,然後A使用公鑰B解密數據。
雖然理論上支持4種情形,但在SSH的身份驗證階段,SSH只支持服務端保留公鑰,客戶端保留私鑰的方式,所以方式只有兩種:客戶端生成密鑰對,將公鑰分發給服務端;服務端生成密鑰對,將私鑰分發給客戶端。只不過出於安全性和便利性,一般都是客戶端生成密鑰對並分發公鑰。後文將給出這兩種分發方式的示例。
1.2 SSH概要
(1).SSH是傳輸層和應用層上的安全協議,它只能通過加密連接雙方會話的方式來保證連接的安全性。當使用ssh連接成功後,將建立客戶端和服務端之間的會話,該會話是被加密的,之後客戶端和服務端的通信都將通過會話傳輸。
(2).SSH服務的守護進程為sshd,預設監聽在22埠上。
(3).所有ssh客戶端工具,包括ssh命令,scp,sftp,ssh-copy-id等命令都是藉助於ssh連接來完成任務的。也就是說它們都連接服務端的22埠,只不過連接上之後將待執行的相關命令轉換傳送到遠程主機上,由遠程主機執行。
(4).ssh客戶端命令(ssh、scp、sftp等)讀取兩個配置文件:全局配置文件/etc/ssh/ssh_config和用戶配置文件~/.ssh/config。實際上命令行上也可以傳遞配置選項。它們生效的優先順序是:命令行配置選項 > ~/.ssh/config > /etc/ssh/ssh_config。
(5).ssh涉及到兩個驗證:主機驗證和用戶身份驗證。通過主機驗證,再通過該主機上的用戶驗證,就能唯一確定該用戶的身份。一個主機上可以有很多用戶,所以每台主機的驗證只需一次,但主機上每個用戶都需要單獨進行用戶驗證。
(6).ssh支持多種身份驗證,最常用的是密碼驗證機制和公鑰認證機制,其中公鑰認證機制在某些場景實現雙機互信時幾乎是必須的。雖然常用上述兩種認證機制,但認證時的順序預設是gssapi-with-mic,hostbased,publickey,keyboard-interactive,password。註意其中的主機認證機制hostbased不是主機驗證,由於主機認證用的非常少(它所讀取的認證文件為/etc/hosts.equiv或/etc/shosts.equiv),所以網路上比較少見到它的相關介紹。總的來說,通過在ssh配置文件(註意不是sshd配置文件)中使用指令PreferredAuthentications改變認證順序不失為一種驗證的效率提升方式。
(7).ssh客戶端其實有不少很強大的功能,如埠轉發(隧道模式)、代理認證、連接共用(連接復用)等。
(8).ssh服務端配置文件為/etc/ssh/sshd_config,註意和客戶端的全局配置文件/etc/ssh/ssh_config區分開來。
(9).最重要的一點,ssh登錄時會請求分配一個偽終端。但有些身份認證程式如sudo可以禁止這種類型的終端分配,導致ssh連接失敗。例如使用ssh執行sudo命令時sudo就會驗證是否要分配終端給ssh。
1.3 SSH認證過程分析
假如從客戶端A(172.16.10.5)連接到服務端B(172.16.10.6)上,將包括主機驗證和用戶身份驗證兩個過程,以RSA非對稱加密演算法為例。
[root@xuexi ~]# ssh 172.16.10.6
服務端B上首先啟動了sshd服務程式,即開啟了ssh服務,打開了22埠(預設)。
1.3.1 主機驗證過程
當客戶端A要連接B時,首先將進行主機驗證過程,即判斷主機B是否是否曾經連接過。
判斷的方法是讀取~/.ssh/known_hosts文件和/etc/ssh/known_hosts文件,搜索是否有172.16.10.6的主機信息(主機信息稱為host key,表示主機身份標識)。如果沒有搜索到對應該地址的host key,則詢問是否保存主機B發送過來的host key,如果搜索到了該地址的host key,則將此host key和主機B發送過來的host key做比對,如果完全相同,則表示主機A曾經保存過主機B的host key,無需再保存,直接進入下一個過程——身份驗證,如果不完全相同,則提示是否保存主機B當前使用的host key。
詢問是否保存host key的過程如下所示:
[root@xuexi ~]# ssh 172.16.10.6 The authenticity of host '172.16.10.6 (172.16.10.6)' can't be established. RSA key fingerprint is f3:f8:e2:33:b4:b1:92:0d:5b:95:3b:97:d9:3a:f0:cf. Are you sure you want to continue connecting (yes/no)? yes
或者windows端使用圖形界面ssh客戶端工具時:
在說明身份驗證過程前,先看下known_hosts文件的格式。以~/.ssh/known_hosts為例。
[root@xuexi ~]# cat ~/.ssh/known_hosts 172.16.10.6 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC675dv1w+GDYViXxqlTspUHsQjargFPSnR9nEqCyUgm5/32jXAA3XTJ4LUGcDHBuQ3p3spW/eO5hAP9eeTv5HQzTSlykwsu9He9w3ee+TV0JjBFulfBR0weLE4ut0PurPMbthE7jIn7FVDoLqc6o64WvN8LXssPDr8WcwvARmwE7pYudmhnBIMPV/q8iLMKfquREbhdtGLzJRL9DrnO9NNKB/EeEC56GY2t76p9ThOB6ES6e/87co2HjswLGTWmPpiqY8K/LA0LbVvqRrQ05+vNoNIdEfk4MXRn/IhwAh6j46oGelMxeTaXYC+r2kVELV0EvYV/wMa8QHbFPSM6nLz
該文件中,每行一個host key,行首是主機名,它是搜索host key時的索引,主機名後的內容即是host key部分。以此文件為例,它表示客戶端A曾經試圖連接過172.16.10.6這個主機B,並保存了主機B的host key,下次連接主機B時,將搜索主機B的host key,並與172.16.10.6傳送過來的host key做比較,如果能匹配上,則表示該host key確實是172.16.10.6當前使用的host key,如果不能匹配上,則表示172.16.10.6修改過host key,或者此文件中的host key被修改過。
那麼主機B當前使用的host key保存在哪呢?在/etc/ssh/ssh_host*文件中,這些文件是服務端(此處即主機B)的sshd服務程式啟動時重建的。以rsa演算法為例,則保存在/etc/ssh/ssh_host_rsa_key和/etc/ssh/ssh_host_rsa_key.pub中,其中公鑰文件/etc/ssh/ssh_host_rsa_key.pub中保存的就是host key。
[root@xuexi ~]# cat /etc/ssh/ssh_host_rsa_key.pub # 在主機B上查看 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC675dv1w+GDYViXxqlTspUHsQjargFPSnR9nEqCyUgm5/32jXAA3XTJ4LUGcDHBuQ3p3spW/eO5hAP9eeTv5HQzTSlykwsu9He9w3ee+TV0JjBFulfBR0weLE4ut0PurPMbthE7jIn7FVDoLqc6o64WvN8LXssPDr8WcwvARmwE7pYudmhnBIMPV/q8iLMKfquREbhdtGLzJRL9DrnO9NNKB/EeEC56GY2t76p9ThOB6ES6e/87co2HjswLGTWmPpiqY8K/LA0LbVvqRrQ05+vNoNIdEfk4MXRn/IhwAh6j46oGelMxeTaXYC+r2kVELV0EvYV/wMa8QHbFPSM6nLz
發現/etc/ssh/ssh_host_rsa_key.pub文件內容和~/.ssh/known_hosts中該主機的host key部分完全一致,只不過~/.ssh/known_hosts中除了host key部分還多了一個主機名,這正是搜索主機時的索引。
綜上所述,在主機驗證階段,服務端持有的是私鑰,客戶端保存的是來自於服務端的公鑰。註意,這和身份驗證階段密鑰的持有方是相反的。
實際上,ssh並非直接比對host key,因為host key太長了,比對效率較低。所以ssh將host key轉換成host key指紋,然後比對兩邊的host key指紋即可。指紋格式如下:
[root@xuexi ~]# ssh 172.16.10.6 The authenticity of host '172.16.10.6 (172.16.10.6)' can't be established. RSA key fingerprint is f3:f8:e2:33:b4:b1:92:0d:5b:95:3b:97:d9:3a:f0:cf. Are you sure you want to continue connecting (yes/no)? yes
host key的指紋可由ssh-kegen計算得出。例如,下麵分別是主機A(172.16.10.5)保存的host key指紋,和主機B(172.16.10.6)當前使用的host key的指紋。可見它們是完全一樣的。
[root@xuexi ~]# ssh-keygen -l -f ~/.ssh/known_hosts 2048 f3:f8:e2:33:b4:b1:92:0d:5b:95:3b:97:d9:3a:f0:cf 172.16.10.6 (RSA) [root@xuexi ~]# ssh-keygen -l -f /etc/ssh/ssh_host_rsa_key 2048 f3:f8:e2:33:b4:b1:92:0d:5b:95:3b:97:d9:3a:f0:cf (RSA)
其實ssh還支持host key模糊比較,即將host key轉換為圖形化的指紋。這樣,圖形結果相差大的很容易就比較出來。之所以說是模糊比較,是因為對於非常近似的圖形化指紋,ssh可能會誤判。圖形化指紋的生成方式如下:只需在上述命令上加一個"-v"選項進入詳細模式即可。
[root@xuexi ~]# ssh-keygen -lv -f ~/.ssh/known_hosts 2048 f3:f8:e2:33:b4:b1:92:0d:5b:95:3b:97:d9:3a:f0:cf 172.16.10.6 (RSA) +--[ RSA 2048]----+ | | | | | . | | o | | S. . + | | . +++ + . | | B.+.= . | | + B. +. | | o.+. oE | +-----------------+
1.3.2 身份驗證過程
主機驗證通過後,將進入身份驗證階段。SSH支持多種身份驗證機制,它們的驗證順序如下:gssapi-with-mic,hostbased,publickey,keyboard-interactive,password,但常見的是密碼認證機制(password)和公鑰認證機制(public key)。當公鑰認證機制未通過時,再進行密碼認證機制的驗證。這些認證順序可以通過ssh配置文件(註意,不是sshd的配置文件)中的指令PreferredAuthentications改變。
如果使用公鑰認證機制,客戶端A需要將自己生成的公鑰(~/.ssh/id_rsa.pub)發送到服務端B的~/.ssh/authorized_keys文件中。當進行公鑰認證時,客戶端將告訴服務端要使用哪個密鑰對,並告訴服務端它已經訪問過密鑰對的私鑰部分~/.ssh/id_rsa(不能直接提供給服務端匹配檢測,因為私鑰不能泄露),然後服務端將檢測密鑰對的公鑰部分,判斷該客戶端是否允許通過認證。如果認證不通過,則進入下一個認證機制,以密碼認證機製為例。
當使用密碼認證時,將提示輸入要連接的遠程用戶的密碼,輸入正確則驗證通過。
1.3.3 驗證通過
當主機驗證和身份驗證都通過後,分兩種情況:直接登錄或執行ssh命令行中給定某個命令。如:
[root@xuexi ~]# ssh 172.16.10.6 [root@xuexi ~]# ssh 172.16.10.6 'echo "haha"'
(1).前者ssh命令行不帶任何命令參數,表示使用遠程主機上的某個用戶(此處為root用戶)登錄到遠程主機172.16.10.6上,所以遠程主機會為ssh分配一個偽終端,併進入bash環境。
(2).後者ssh命令行帶有命令參數,表示在遠程主機上執行給定的命令【echo "haha"】。ssh命令行上的遠程命令是通過fork ssh-agent得到的子進程來執行的,當命令執行完畢,子進程消逝,ssh也將退出,建立的會話和連接也都將關閉。(之所以要在這裡明確說明遠程命令的執行過程,是為了說明後文將介紹的ssh實現埠轉發時的註意事項)
實際上,在ssh連接成功,登錄或執行命令行中命令之前,可以指定要在遠程執行的命令,這些命令放在~/.ssh/rc或/etc/ssh/rc文件中,也就是說,ssh連接建立之後做的第一件事是在遠程主機上執行這兩個文件中的命令。
1.4 各種文件分佈
以主機A連接主機B為例,主機A為SSH客戶端,主機B為SSH服務端。
在服務端即主機B上:
- /etc/ssh/sshd_config :ssh服務程式sshd的配置文件。
- /etc/ssh/ssh_host_* :服務程式sshd啟動時生成的服務端公鑰和私鑰文件。如ssh_host_rsa_key和ssh_host_rsa_key.pub。
- :其中.pub文件是主機驗證時的host key,將寫入到客戶端的~/.ssh/known_hosts文件中。
- :其中私鑰文件嚴格要求許可權為600,若不是則sshd服務可能會拒絕啟動。
- ~/.ssh/authorized_keys:保存的是基於公鑰認證機制時來自於客戶端的公鑰。在基於公鑰認證機制認證時,服務端將讀取該文件。
在客戶端即主機A上:
- /etc/ssh/ssh_config :客戶端的全局配置文件。
- ~/.ssh/config :客戶端的用戶配置文件,生效優先順序高於全局配置文件。一般該文件預設不存在。該文件對許可權有嚴
- :格要求只對所有者有讀/寫許可權,對其他人完全拒絕寫許可權。
- ~/.ssh/known_hosts :保存主機驗證時服務端主機host key的文件。文件內容來源於服務端的ssh_host_rsa_key.pub文件。
- /etc/ssh/known_hosts:全局host key保存文件。作用等同於~/.ssh/known_hosts。
- ~/.ssh/id_rsa :客戶端生成的私鑰。由ssh-keygen生成。該文件嚴格要求許可權,當其他用戶對此文件有可讀許可權時,
- :ssh將直接忽略該文件。
- ~/.ssh/id_rsa.pub :私鑰id_rsa的配對公鑰。對許可權不敏感。當採用公鑰認證機制時,該文件內容需要複製到服務端的
- :~/.ssh/authorized_keys文件中。
- ~/.ssh/rc :保存的是命令列表,這些命令在ssh連接到遠程主機成功時將第一時間執行,執行完這些命令之後才
- :開始登陸或執行ssh命令行中的命令。
- /etc/ssh/rc :作用等同於~/.ssh/rc。
1.5 配置文件簡單介紹
分為服務端配置文件/etc/ssh/sshd_config和客戶端配置文件/etc/ssh/ssh_config(全局)或~/.ssh/config(用戶)。
雖然服務端和客戶端配置文件預設已配置項雖然非常少非常簡單,但它們可配置項非常多。sshd_config完整配置項參見金步國翻譯的sshd_config中文手冊,ssh_config也可以參考sshd_config的配置,它們大部分配置項所描述的內容是相同的。
1.5.1 sshd_config
簡單介紹下該文件中比較常見的指令。
[root@xuexi ~]# cat /etc/ssh/sshd_config
#Port 22 # 服務端SSH埠,可以指定多條表示監聽在多個埠上 #ListenAddress 0.0.0.0 # 監聽的IP地址。0.0.0.0表示監聽所有IP Protocol 2 # 使用SSH 2版本 ##################################### # 私鑰保存位置 # ##################################### # HostKey for protocol version 1 #HostKey /etc/ssh/ssh_host_key # SSH 1保存位置/etc/ssh/ssh_host_key # HostKeys for protocol version 2 #HostKey /etc/ssh/ssh_host_rsa_key # SSH 2保存RSA位置/etc/ssh/ssh_host_rsa _key #HostKey /etc/ssh/ssh_host_dsa_key # SSH 2保存DSA位置/etc/ssh/ssh_host_dsa _key ################################### # 雜項配置 # ################################### #PidFile /var/run/sshd.pid # 服務程式sshd的PID的文件路徑 #ServerKeyBits 1024 # 伺服器生成的密鑰長度 #SyslogFacility AUTH # 使用哪個syslog設施記錄ssh日誌。日誌路徑預設為/var/log/secure #LogLevel INFO # 記錄SSH的日誌級別為INFO #LoginGraceTime 2m # 身份驗證階段的超時時間,若在此超時期間內未完成身份驗證將自動斷開 ################################### # 以下項影響認證速度 # ################################### #UseDNS yes # 指定是否將客戶端主機名解析為IP,以檢查此主機名是否與其IP地址真實對應。預設yes。 # 由此可知該項影響的是主機驗證階段。建議在未配置DNS解析時,將其設置為no,否則主機驗證階段會很慢 ################################### # 以下是和安全有關的配置 # ################################### #PermitRootLogin yes # 是否允許root用戶登錄 #MaxSessions 10 # 最大客戶端連接數量 #GSSAPIAuthentication no # 是否開啟GSSAPI身份認證機制,預設為yes #PubkeyAuthentication yes # 是否開啟基於公鑰認證機制 #AuthorizedKeysFile .ssh/authorized_keys # 基於公鑰認證機制時,來自客戶端的公鑰的存放位置 PasswordAuthentication yes # 是否使用密碼驗證,如果使用密鑰對驗證可以關了它 #PermitEmptyPasswords no # 是否允許空密碼,如果上面的那項是yes,這裡最好設置no ################################### # 以下可以自行添加到配置文件 # ################################### DenyGroups hellogroup testgroup # 表示hellogroup和testgroup組中的成員不允許使用sshd服務,即拒絕這些用戶連接 DenyUsers hello test # 表示用戶hello和test不能使用sshd服務,即拒絕這些用戶連接 ################################### # 以下一項和遠程埠轉發有關 # ################################### #GatewayPorts no # 設置為yes表示sshd允許被遠程主機所設置的本地轉髮端口綁定在非環回地址上 # 預設值為no,表示遠程主機設置的本地轉髮端口只能綁定在環回地址上,見後文"遠程埠轉發"
一般來說,如非有特殊需求,只需修改下監聽埠和UseDNS為no以加快主機驗證階段的速度即可。
配置好後直接重啟啟動sshd服務即可。
[root@xuexi ~]# service sshd restart
1.5.2 ssh_config
需要說明的是,客戶端配置文件有很多配置項和服務端配置項名稱相同,但它們一個是在連接時採取的配置(客戶端配置文件),一個是sshd啟動時開關性的設置(服務端配置文件)。例如,兩配置文件都有GSSAPIAuthentication項,在客戶端將其設置為no,表示連接時將直接跳過該身份驗證機制,而在服務端設置為no則表示sshd啟動時不開啟GSSAPI身份驗證的機制。即使客戶端使用了GSSAPI認證機制,只要服務端沒有開啟,就絕對不可能認證通過。
下麵也簡單介紹該文件。
# Host * # Host指令是ssh_config中最重要的指令,只有ssh連接的目標主機名能匹配此處給定模式時, # 下麵一系列配置項直到出現下一個Host指令才對此次連接生效 # ForwardAgent no # ForwardX11 no # RhostsRSAAuthentication no # RSAAuthentication yes # PasswordAuthentication yes # 是否啟用基於密碼的身份認證機制 # HostbasedAuthentication no # 是否啟用基於主機的身份認證機制 # GSSAPIAuthentication no # 是否啟用基於GSSAPI的身份認證機制 # GSSAPIDelegateCredentials no # GSSAPIKeyExchange no # GSSAPITrustDNS no # BatchMode no # 如果設置為"yes",將禁止passphrase/password詢問。比較適用於在那些不需要詢問提供密 # 碼的腳本或批處理任務任務中。預設為"no"。 # CheckHostIP yes # AddressFamily any # ConnectTimeout 0 # StrictHostKeyChecking ask # 設置為"yes",ssh將從不自動添加host key到~/.ssh/known_hosts文件, # 且拒絕連接那些未知的主機(即未保存host key的主機或host key已改變的主機)。 # 它將強制用戶手動添加host key到~/.ssh/known_hosts中。 # 設置為ask將詢問是否保存到~/.ssh/known_hosts文件。 # 設置為no將自動添加到~/.ssh/known_hosts文件。 # IdentityFile ~/.ssh/identity # ssh v1版使用的私鑰文件 # IdentityFile ~/.ssh/id_rsa # ssh v2使用的rsa演算法的私鑰文件 # IdentityFile ~/.ssh/id_dsa # ssh v2使用的dsa演算法的私鑰文件 # Port 22 # 當命令行中不指定埠時,預設連接的遠程主機上的埠 # Protocol 2,1 # Cipher 3des # 指定ssh v1版本中加密會話時使用的加密協議 # Ciphers aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,aes128-cbc,3des-cbc # 指定ssh v1版本中加密會話時使用的加密協議 # MACs hmac-md5,hmac-sha1,umac-64@openssh.com,hmac-ripemd160 # EscapeChar ~ # Tunnel no # TunnelDevice any:any # PermitLocalCommand no # 功能等價於~/.ssh/rc,表示是否允許ssh連接成功後在本地執行LocalCommand指令指定的命令。 # LocalCommand # 指定連接成功後要在本地執行的命令列表,當PermitLocalCommand設置為no時將自動忽略該配置 # %d表本地用戶家目錄,%h表示遠程主機名,%l表示本地主機名,%n表示命令行上提供的主機名, # p%表示遠程ssh埠,r%表示遠程用戶名,u%表示本地用戶名。 # VisualHostKey no # 是否開啟主機驗證階段時host key的圖形化指紋 Host * GSSAPIAuthentication yes
如非有特殊需求,ssh客戶端配置文件一般只需修改下GSSAPIAuthentication的值為no來改善下用戶驗證的速度即可,另外在有非交互需求時,將StrictHostKeyChecking設置為no以讓主機自動添加host key。
1.6 ssh命令簡單功能
此處先介紹ssh命令的部分功能,其他包括埠轉發的在後文相關內容中解釋,關於連接復用的選項本文不做解釋。
語法:
ssh [options] [user@]hostname [command] 參數說明: -b bind_address :在本地主機上綁定用於ssh連接的地址,當系統有多個ip時才生效。 -E log_file :將debug日誌寫入到log_file中,而不是預設的標準錯誤輸出stderr。 -F configfile :指定用戶配置文件,預設為~/.ssh/config。 -f :請求ssh在工作在後臺模式。該選項隱含了"-n"選項,所以標準輸入將變為/dev/null。 -i identity_file:指定公鑰認證時要讀取的私鑰文件。預設為~/.ssh/id_rsa。 -l login_name :指定登錄在遠程機器上的用戶名。也可以在全局配置文件中設置。 -N :顯式指明ssh不執行遠程命令。一般用於埠轉發,見後文埠轉發的示例分析。 -n :將/dev/null作為標準輸入stdin,可以防止從標準輸入中讀取內容。ssh在後臺運行時預設該項。 -p port :指定要連接遠程主機上哪個埠,也可在全局配置文件中指定預設的連接埠。 -q :靜默模式。大多數警告信息將不輸出。 -T :禁止為ssh分配偽終端。 -t :強制分配偽終端,重覆使用該選項"-tt"將進一步強制。 -v :詳細模式,將輸出debug消息,可用於調試。"-vvv"可更詳細。 -V :顯示版本號並退出。 -o :指定額外選項,選項非常多。 user@hostname :指定ssh以遠程主機hostname上的用戶user連接到的遠程主機上,若省略user部分,則表示使用本地當前用戶。 :如果在hostname上不存在user用戶,則連接將失敗(將不斷進行身份驗證)。 command :要在遠程主機上執行的命令。指定該參數時,ssh的行為將不再是登錄,而是執行命令,命令執行完畢時ssh連接就關閉。
例如,以172.16.10.6主機上的longshuai用戶登錄172.16.10.6。
[root@xuexi ~]# ssh longshuai@172.16.10.6 The authenticity of host '172.16.10.6 (172.16.10.6)' can't be established. ECDSA key fingerprint is 18:d1:28:1b:99:3b:db:20:c7:68:0a:f8:9e:43:e8:b4. Are you sure you want to continue connecting (yes/no)? yes # 主機驗證 Warning: Permanently added '172.16.10.6' (ECDSA) to the list of known hosts. longshuai@172.16.10.6's password: # 用戶驗證 Last login: Wed Jul 5 12:27:29 2017 from 172.16.10.6
此時已經登錄到了172.16.10.6主機上。
[longshuai@xuexi ~]$ hostname -I 172.16.10.6
要退出ssh登錄,使用logout命令或exit命令即可返回到原主機環境。
使用ssh還可以實現主機跳轉,即跳板功能。例如主機B能和A、C通信,但A、C之間不同通信,即A<-->B<-->C<-x->A的情形。如果要從A登陸到C,則可以藉助B這個跳板登錄到C。此處一個簡單示例為:從172.16.10.5登錄到172.16.10.6,再以此為基礎登錄到172.16.100.3上。
[root@xuexi ~]# ssh 172.16.10.6 The authenticity of host '172.16.10.6 (172.16.10.6)' can't be established. RSA key fingerprint is f3:f8:e2:33:b4:b1:92:0d:5b:95:3b:97:d9:3a:f0:cf. Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added '172.16.10.6' (RSA) to the list of known hosts. Last login: Wed Jul 5 12:36:51 2017 from 172.16.10.6
[root@xuexi ~]# ssh 172.16.10.3 The authenticity of host '172.16.10.3 (172.16.10.3)' can't be established. ECDSA key fingerprint is 18:d1:28:1b:99:3b:db:20:c7:68:0a:f8:9e:43:e8:b4. Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added '172.16.10.3' (ECDSA) to the list of known hosts. root@172.16.10.3's password: Last login: Thu Jun 29 12:38:56 2017 from 172.16.10.6
[root@xuexi ~]# hostname -I 172.16.10.3 172.16.10.4
同樣,在退出時,也是一層一層退出的。
[root@xuexi ~]# exit logout Connection to 172.16.10.3 closed. [root@xuexi ~]# hostname -I 172.16.10.6 [root@xuexi ~]# exit logout Connection to 172.16.10.6 closed.
註意,由於在藉助172.16.10.6當跳板連接到172.16.10.3,所以172.16.10.3的host key是添加到172.16.10.3上而非172.16.10.5上的。
如果在命令行給出了要執行的命令,預設ssh將工作在前臺,如果同時給定了"-f"選項,則ssh工作在後臺。但儘管是工作在後臺,當遠程執行的命令如果有消息返回時,將隨時可能顯示在本地。當遠程命令執行完畢後,ssh連接也將立即關閉。
[root@xuexi ~]# ssh 172.16.10.6 'sleep 5' # 在前臺睡眠5秒鐘 [root@xuexi ~]# ssh 172.16.10.6 -f 'sleep 5;echo over' # 在後臺睡眠5秒,睡眠完成後echo一段信息
由於第二條命令是放在後臺執行的,所以該ssh一建立完成ssh會話就立即返回本地bash環境,但當5秒之後,將在本地突然顯示"over"。
ssh執行遠程命令預設允許從標準輸入中讀取數據然後傳輸到遠程。可以使用"-n"選項,使得標準輸入重定向為/dev/null。例如:
[root@xuexi ~]# echo haha | ssh 172.16.10.6 'cat' haha [root@xuexi ~]# ssh 172.16.10.6 'cat' </etc/fstab
再看如下兩條命令:
[root@xuexi ~]# tar zc /tmp/* | ssh 172.16.10.6 'cd /tmp;tar xz' [root@xuexi ~]# ssh 172.16.10.6 'tar cz /tmp' | tar xz
第一條命令將/tmp下文件歸檔壓縮,然後傳送到遠程主機上並被解包;第二條命令將遠程主機上的/tmp目錄歸檔壓縮,並傳輸到本地解包。所以它們實現了拷貝的功能。
不妨再分析下麵的命令,該命令改編自ssh-copy-id腳本中的主要命令。如果不知道ssh-copy-id命令是乾什麼的,後文有介紹。
[root@xuexi ~]# cat ~/.ssh/id_rsa.pub | ssh 172.16.10.6 "umask 077; test -d ~/.ssh || mkdir ~/.ssh ; cat >> ~/.ssh/authorized_keys"
該命令首先建立ssh連接,併在遠程執行"umask 077"臨時修改遠程的umask值,使得遠程創建的目錄許可權為700,然後判斷遠程主機上是否有~/.ssh目錄,如果沒有則創建,最後從標準輸入中讀取本地公鑰文件~/.ssh/id_rsa.pub的內容並將其追加到~/.ssh/authorized_keys文件中。
如果將此命令改為如下命令,使用ssh的"-n"選項,並將追加重定向改為覆蓋重定向符號。
[root@xuexi ~]# cat ~/.ssh/id_rsa.pub | ssh -n 172.16.10.6 "umask 077; test -d ~/.ssh || mkdir ~/.ssh ; cat > ~/.ssh/authorized_keys"
該命令的結果是清空遠程主機172.16.10.6上的~/.ssh/authorized_keys文件,因為ssh的"-n"選項強行改變了ssh讀取的標準輸入為/dev/null。
1.7 scp命令及過程分析
scp是基於ssh的遠程拷貝命令,也支持本地拷貝,甚至支持遠程到遠程的拷貝。
scp由於基於ssh,所以其埠也是使用ssh的埠。其實,scp拷貝的實質是使用ssh連接到遠程,並使用該連接來傳輸數據。下文有scp執行過程的分析。
另外,scp還非常不占資源,不會提高多少系統負荷,在這一點上,rsync遠不及它。雖然 rsync比scp會快一點,但rsync是增量拷貝,要判斷每個文件是否修改過,在小文件眾多的情況下,判斷次數非常多,導致rsync效率較差,而scp基本不影響系統正常使用。
scp每次都是全量拷貝,在某些情況下,肯定是不及rsync的。
scp [-12BCpqrv] [-l limit] [-o ssh_option] [-P port] [[user@]host1:]src_file ... [[user@]host2:]dest_file 選項說明: -1:使用ssh v1版本,這是預設使用協議版本 -2:使用ssh v2版本 -C:拷貝時先壓縮,節省帶寬 -l limit:限制拷貝速度,Kbit/s,1Byte=8bit,所以"-l 800"表示的速率是100K/S -o ssh_option:指定ssh連接時的特殊選項,一般用不上。 -P port:指定目標主機上ssh埠,大寫的字母P,預設是22埠 -p:拷貝時保持源文件的mtime,atime,owner,group,privileges -r:遞歸拷貝,用於拷貝目錄。註意,scp拷貝遇到鏈接文件時,會拷貝鏈接的源文件內容填充到目標文件中(scp的本質就是填充而非拷貝) -v:輸出詳細信息,可以用來調試或查看scp的詳細過程,分析scp的機制
src_file是源位置,dest_file是目標位置,即將src_file複製到dest_file,其中src_file可以指定多個。由於源位置和目標位置都可以使用本地路徑和遠程路徑,所以scp能實現本地拷貝到遠程、本地拷貝到本地、遠程拷貝到本地、遠程拷貝到另一個遠程。其中遠程路徑的指定格式為"user@hostname:/path",可以省略user,也可以省略":/path",省略":/path"時表示拷貝到目的用戶的家目錄下。
註意:scp拷貝是強制覆蓋型拷貝,當有重名文件時,不會進行任何詢問。
例如:
(1).本地拷貝到本地:/etc/fstab-->/tmp/a.txt。
[root@xuexi ~]# scp /etc/fstab /tmp/a.txt
(2).本地到遠程:/etc/fstab-->172.16.10.6:/tmp/a.txt。
[root@xuexi ~]# scp /etc/fstab 172.16.10.6:/tmp fstab 100% 805 0.8KB/s 00:00
(3).遠程到本地:172.16.10.6:/etc/fstab-->/tmp/a.txt。
[root@xuexi ~]# scp 172.16.10.6:/etc/fstab /tmp/a.txt fstab 100% 501 0.5KB/s 00:00
(4).遠程路徑1到遠程路徑2:172.16.10.6:/etc/fstab-->/172.16.10.3:/tmp/a.txt。
[root@xuexi ~]# scp 172.16.10.6:/etc/fstab 172.16.10.3:/tmp/a.txt fstab 100% 501 0.5KB/s 00:00 Connection to 172.16.10.6 closed.
1.7.1 scp拷貝機制分析
scp的拷貝實質是建立ssh連接,然後通過此連接來傳輸數據。如果是遠程1拷貝到遠程2,則是將scp命令轉換後發送到遠程1上執行,在遠程1上建立和遠程2的ssh連接,並通過此連接來傳輸數據。
在遠程複製到遠程的過程中,例如在本地(172.16.10.5)執行scp命令將A主機(172.16.10.6)上的/tmp/copy.txt複製到B主機(172.16.10.3)上的/tmp目錄下,如果使用-v選項查看調試信息的話,會發現它的步驟類似是這樣的。
# 以下是從結果中提取的過程 # 首先輸出本地要執行的命令 Executing: /usr/bin/ssh -v -x -oClearAllForwardings yes -t -l root 172.16.10.6 scp -v /tmp/copy.txt root@172.16.10.3:/tmp # 從本地連接到A主機 debug1: Connecting to 172.16.10.6 [172.16.10.6] port 22. debug1: Connection established. # 要求驗證本地和A主機之間的連接 debug1: Next authentication method: password root@172.16.10.6's password: # 將scp命令行修改後發送到A主機上 debug1: Sending command: scp -v /tmp/copy.txt root@172.16.10.3:/tmp # 在A主機上執行scp命令 Executing: program /usr/bin/ssh host 172.16.10.3, user root, command scp -v -t /tmp # 驗證A主機和B主機之間的連接 debug1: Next authentication method: password root@172.16.10.3's password: # 從A主機上拷貝源文件到最終的B主機上 debug1: Sending command: scp -v -t /tmp Sending file modes: C0770 24 copy.txt Sink: C0770 24 copy.txt copy.txt 100% 24 0.0KB/s # 關閉本地主機和A主機的連接 Connection to 172.16.10.6 closed.
也就是說,遠程主機A到遠程主機B的複製,實際上是將scp命令行從本地傳輸到主機A上,由A自己去執行scp命令。也就是說,本地主機不會和主機B有任何交互行為,本地主機就像是一個代理執行者一樣,只是幫助傳送scp命令行以及幫助顯示信息。
其實從本地主機和主機A上的~/.ssh/know_hosts文件中可以看出,本地主機只是添加了主機A的host key,並沒有添加主機B的host key,而在主機A上則添加了主機B的host key。
1.8 基於公鑰認證機制實現雙機互信
在身份驗證階段,由於預設情況下基於公鑰認證的機制順序優先於基於密碼認證的機制,所以基於公鑰認證身份,就可以免輸入密碼,即實現雙機互信(實際上只是單方向的信任)。
基於公鑰認證機制的認證過程在前文已經詳細說明過了,如還不清楚,請跳回上文。
1.8.1 實現步驟
以下是實現基於公鑰認證的實現步驟:
(1).在客戶端使用ssh-keygen生成密鑰對,存放路徑按照配置文件的指示,預設是在~/.ssh/目錄下。
[root@xuexi ~]# ssh-keygen -t rsa # -t參數指定演算法,可以是rsa或dsa Generating public/private rsa key pair. Enter file in which to save the key (/root/.ssh/id_rsa): # 詢問私鑰保存路徑 Enter passphrase (empty for no passphrase): # 詢問是否加密私鑰文件 Enter same passphrase again: Your identification has been saved in /root/.ssh/id_rsa. Your public key has been saved in /root/.ssh/id_rsa.pub.
如果不想被詢問,則可以使用下麵一條命令完成:"-f"指定私鑰文件,"-P"指定passphrase,或者"-N"也一樣。
[root@xuexi ~]# ssh-keygen -t rsa -f ~/.ssh/id_rsa -P '' # 指定加密私鑰文件的密碼為空密碼,即不加密 [root@xuexi ~]# ssh-keygen -t rsa -f ~/.ssh/id_rsa -N '' # 同上
查看~/.ssh/目錄下私鑰的許可權。私鑰文件有嚴格的許可權要求,當私鑰文件的非所有者有可讀許可權時,將直接忽略該私鑰文件導致公鑰認證失敗。
[root@xuexi ~]# ls -l ~/.ssh total 12 -rw------- 1 root root 1671 Jun 29 00:18 id_rsa # 私鑰許可權必須600,屬主為自己 -rw-r--r-- 1 root root 406 Jun 29 00:18 id_rsa.pub -rw-r--r-- 1 root root 393 Jun 29 05:56 known_hosts
(2).將上面生成的公鑰使用ssh-copy-id分發(即複製)到遠程待信任主機上。
ssh-copy-id用法很簡單,只需指定待信任主機及目標用戶即可。如果生成的公鑰文件,路徑不是~/.ssh/id_rsa.pub,則使用"-i"選項指定要分發的公鑰。
ssh-copy-id [-i [identity_file]] [user@]machine
例如,將公鑰分發到172.16.10.6上的root用戶家目錄下:
[root@xuexi ~]# ssh-copy-id