目錄(?)[+]
轉(zhuǎn)載自:http://blog.pkufranky.com/2012/08/ssh-agent-forwarding-guide/
ssh-agent的manual寫得倒是挺詳細,可看了好幾次都沒怎樣弄明白。08年在網(wǎng)上找到了非常好的1篇文章,An Illustrated Guide to SSH Agent Forwarding (后文簡稱agent guide), 將ssh的各種認證方法講得非常之詳細。 文章從密碼認證,公鑰認證,使用agent和agent forward的公鑰認證幾個方面,逐漸的將全部進程剖析得非常全面。 看完以后總算是入了門,為此寫了1篇簡短的博文。
本周為了做ssh agent相干的培訓(xùn),多方查看資料,包括ssh/sshd的manual, 相干RFC, wikipedia。 終究算是把密碼學(xué)和ssh相干東西理解得更深入了。然后重新將agent guide看了看,發(fā)現(xiàn)了1些問題。agent guide是2006年寫的,而06年SSH⑵剛剛出來,因此文章是基于SSH⑴的。雖然ssh agent的基本原理還是對的,但有的地方(主要是認證部份)已不正確了。
所以本文針對SSH⑵,將不準確的地方重新梳理1下,并添加了1些SSH基石(密碼學(xué))相干的內(nèi)容。
先從密碼學(xué)說起。 現(xiàn)代之前,密碼學(xué)(cryptography)主要專指加密(encryption)解密(decryption)。1組配對的加密和解密算法稱為cipher. 加解密的具體運作由兩部份決定:1個是算法(algorithm),另外一個是鑰匙(key).
現(xiàn)代密碼學(xué)主要分為對稱鑰匙密碼學(xué)和公鑰密碼學(xué)(非對稱鑰匙密碼學(xué))。對稱鑰匙密碼學(xué)指的是加密方和解密方都具有相同的密鑰。對稱鑰匙加密算法包括3DES, AES, Blowfish等。 對稱鑰匙密碼學(xué)依賴于鑰匙的保密性,其為難的困難是:當(dāng)安全的通道不存在于雙方時,如何安全傳送這1雙方同享的密鑰?如果有通道可以安全地建立鑰匙,何不使用現(xiàn)有的通道。這個“雞生蛋、蛋生雞”的矛盾是終年以來密碼學(xué)沒法在真實世界利用的阻礙。直到1976年,公鑰密碼學(xué)的誕生,安全通道的問題才得以很好的解決。這1點下面講SSL/TLS的時候會提到。
公鑰密碼學(xué),則使用1對公鑰和私鑰,通過公鑰加密,私鑰解密。公鑰和私鑰是相干的,但很難從1個推導(dǎo)出另外1個。公鑰密碼學(xué)不存在安全傳送密鑰的問題,由于公鑰可以對外公然,明文傳送。
公鑰密碼學(xué)包括公鑰加密算法和數(shù)字簽名算法。RSA是最多見的公鑰加密算法。RSA算法由3步構(gòu)成: 公鑰私鑰的生成,加密和解密。公鑰和私鑰中的任何1個可用作加密,另外一個則用作解密。
RSA也可用作數(shù)字簽名,甲方將消息的散列值使用私鑰加密,作為簽名附在消息后面,乙方收到消息后使用公鑰將簽名解密,然后和消息計算的散列值進行對照。假設(shè)二者符合的話,那末乙方就能夠知道發(fā)信人持有甲的私鑰,和這個消息在傳播路徑上沒有被篡改過。
DSA是經(jīng)常使用的數(shù)字簽名算法,但不能用作加密解密。
如何利用密碼學(xué)來安全傳輸數(shù)據(jù)呢?目前最經(jīng)常使用的安全數(shù)據(jù)傳輸協(xié)議(利用層協(xié)議)是SSL/TLS. SSL (Secure Socket Layer)協(xié)議分為1.0, 2.0(1995),3.0(1996)3個版本。TLS (Transport Layer Security)則是SSL的后繼協(xié)議,分為1.0, 1.1,1.2(2008)3個版本。TLS在SSL3.0的基礎(chǔ)上改動其實不大,但和SSL3.0不能互操作(interoperate)。TLS中包括將連接降級到SSL3.0的方法,因此也寫作SSL/TLS.
TLS1般使用基于非對稱密碼學(xué)的Diffie-Hellman key exchange來安全傳送同享密鑰,然后使用對稱鑰匙加密算法和這1同享密鑰對傳送的數(shù)據(jù)進行加密。很多利用層的協(xié)議都可通過SSL/TLS來安全傳輸數(shù)據(jù),比如最多見的HTTPS, 郵件傳輸服務(wù)協(xié)議(SMTP)等。
Secure Sockets Layer (SSL) uses Diffie-Hellman key exchange if the client does not have a public-private key pair and a published certificate in the Public Key Infrastructure, and Public Key Cryptography if the user does have both the keys and the credential.
終究到正題了,下面開始講SSH.
那SSH (Secure Shell)和SSL/TLS是甚么關(guān)系呢?SSH也是1個網(wǎng)絡(luò)協(xié)議,用來進行安全數(shù)據(jù)交換,遠程shell服務(wù)和命令履行等。SSH由傳輸,認證和連接等協(xié)議組成。SSH的傳輸協(xié)議類似SSL/TLS (Diffie-Hellman key exchange和對稱鑰匙加密)。
本文的重點是SSH的認證部份。client和server通過key exchange取得同享密鑰(shared session key)后,所有以后的傳輸數(shù)據(jù)都進行了加密。然落后入認證部份,認證成功后,則雙向連接通道建立,通常是login shell.
來自securecrt官網(wǎng)關(guān)于shared session key的描寫
Session keys are the “shared keys” described above and are randomly generated by both the client and the server during establishment of a connection. Both the client and host use the same session key to encrypt and decrypt data although a different key is used for the send and receive channels. Session keys are generated after host authentication is successfully performed but before user authentication so that usernames and passwords can be sent encrypted. These keys may be replaced at regular intervals (e.g., every one to two hours) during the session and are destroyed at its conclusion.
SSH認證有多種方法,本文側(cè)重講最多見了兩種:密碼認證和公鑰認證。
密碼認證最簡單:
基于密碼認證的缺點是
公鑰認證詳細協(xié)議見RFC4252的publickey部份
公鑰認證需要先在本地機器生成公鑰私鑰對,然后將公鑰放到目標機器的$HOME/.ssh/authorized_keys中。具體進程以下
$HOME/.ssh/authorized_keys
,肯定公鑰是不是可用作認證并驗證簽名的合法性, 如果二者都ok, 則通過認證如果公鑰認證失敗,ssh還會嘗試其他認證策略,比如密碼認證。多個認證策略的嘗試順序和服務(wù)器端沒關(guān)系,由客戶真?zhèn)€配置來決定。
需要說明的是,即便把本機的公鑰(如.ssh/id_rsa.pub
)刪除掉,認證依然可以成功。那第3步中提到的公鑰從哪里來的呢?實際上,上面(如第2步)提到的私鑰(如.ssh/id_rsa
)是廣義的,既包括了私鑰,也包括了公鑰,也有可能還包括了其他信息(比如證書)。比如通過ssh-keygen -y ~/.ssh/id_rsa
就能夠看到id_rsa
里面的公鑰。
用作認證的私鑰最好通過passphrase進行加密,否則會有很大安全隱患,只要私鑰泄漏,他人就可以訪問你能訪問的所有遠程機器。
公鑰認證由于需要配置公鑰私鑰,初始配置略微麻煩1些,但好處是所有機器只需配置1組公私鑰對就能夠了。由于只有1個私鑰,沒必要設(shè)置多個密碼,因此可以為其設(shè)置比較強的密碼。并且僅當(dāng)私鑰和密碼1同丟失時才有風(fēng)險,但這個幾率非常小。
不過依然煩人的是,每次登陸都得輸入passphrase。
為解決每次登陸遠程機器都需要輸入passphrase的問題,ssh-agent被引入了。ssh-agent啟動后,可通過ssh-add將私鑰加入agent. ssh-add會提示用戶輸入passphrase以解密私鑰,然后將解密后的私鑰納入agent管理。agent可同時管理多個私鑰。
連接服務(wù)器的步驟以下:
$HOME/.ssh/authorized_keys
,肯定公鑰是不是可用作認證并驗證簽名的合法性, 如果二者都ok, 則通過認證如果ssh-agent中有多個私鑰, 會順次嘗試,直到認證通過或遍歷所有私鑰.
在全部進程中,私鑰只存在于agent的內(nèi)部(內(nèi)存中), ssh client并沒有獲得到私鑰。
使用ssh-agent后,只需在將key納入agent管理時輸入passphrase,以后的ssh相干操作就沒必要輸入passphrase了。但如果從本機A登陸機器B后,又想從B登陸C (或從B傳輸文件到C),依然需要輸入passphrase (如果B上也配置了用戶的私鑰)或password。還是比較麻煩。
幸虧,ssh agent forwarding解決了這1問題。
server: ssh client向本地(server)的agent要求, 得到私鑰簽名的包括username和公鑰等信息的message。
注意server上其實ssh-agent壓根就沒有啟動,ssh client只是檢查$SSH_AUTH_SOCK
這個環(huán)境變量是不是存在,如果存在,則和這個變量指定的domain socket進行通訊。而這個domain socket實際上是由server上的sshd創(chuàng)建的。所以ssh client實際上是和sshd在通訊。
而server的sshd并沒有私鑰信息,所以sshd做的事情實際上是轉(zhuǎn)發(fā)該要求到homepc的ssh client,再由該client將要求轉(zhuǎn)發(fā)給本地(homepc)的agent。該agent將需要的消息和簽名準備終了后,再將此數(shù)據(jù)按原路返回到server的ssh client. 路徑以下所示
這下明白為何叫agent forwarding(轉(zhuǎn)發(fā))了吧,就是所有中間節(jié)點的sshd和ssh都充當(dāng)了數(shù)據(jù)轉(zhuǎn)發(fā)的角色,1直將私鑰操作的request轉(zhuǎn)發(fā)到了本機的agent,然后再將agent的response原路返回。
server: ssh client向目標機器server2發(fā)送此message和簽名
$HOME/.ssh/authorized_keys
,肯定公鑰是不是可用作認證并驗證簽名的合法性, 如果二者都ok, 則通過認證上面只是示例,從server2,還可以類似的無密碼登陸到server3。事實上,通過ssh agent forwarding, 能實現(xiàn)任意級別的無密碼登陸。并且私鑰只保存在本地的機器上,保證了私鑰的安全。
agent forwarding功能是默許關(guān)閉的,為實現(xiàn)任意級別無密碼登陸,在ssh到其他機器時,1定要記得添加-A
參數(shù), 以打開agent forwarding (在目標機器上會生成$SSH_AUTH_SOCK環(huán)境變量)。 比如ssh -A server2
。
agent forwarding打開以后,也會有安全的風(fēng)險。如果用戶A通過ssh連接server并打開了agent forwarding,由于server上的root用戶也有權(quán)限訪問與agent通訊的套接字,只要root用戶將$SSH_AUTH_SOCK
指向用戶A對應(yīng)的套接字地址,就能夠以A的身份訪問其它A可以訪問的機器。因此請確保agent forwarding僅在可信任的服務(wù)器上打開。
本文主要從基本原理角度對ssh認證和agent相干問題進行了分析。下文會講講最好實踐。
ps:
使用步驟以下:
1 eval `ssh-agent`
2 ssh-add
3 ssh -A 要連接的主機