ssh 配置详解
一)客戶端與服務端的通訊認證流程: 第一階段: 雙方協商SSH版本號和協議,協商過程數據不加密. SSH-<主協議版本號>.<次協議版本號>-<軟件版本號> 對映如下: SSH-2.0-OpenSSH_5.3(我們可以通過telnet localhost 22得到SSH的版本號) 第二階段: 雙方協商RSA/DSA主機密鑰,數據加密算法,消息摘要. 其中主機密鑰用于確認服務端的身份,數據加密算法用于加密通信數據,消息摘要用于校驗數據的完整性,登錄認證方式. 主要思想是服務端提供各種加密/認證方式,客戶端在這中間選擇加密/認證方式. 第三階段: 由于雙方已經確認了可以使用的加密算法,消息摘要,協議版本號,主機密鑰等信息,這階段由客戶端根據選擇的認證方式發起登錄驗證申請. 服務端對客戶端提供的密碼等信息進行校驗.如認證不通過,則試圖進行下一種認證方式的申核,直到成功/失敗,或者超時. 第四階段: 客戶端如果校驗成功,則服務端會創建一個客戶端的session(進程),同時會轉送環境變量,最后給客戶端一個bash的機會. 我們在客戶端用debug的方式進行登錄,注意這里只用了debug1. ssh -v 192.168.27.142 ?? OpenSSH_5.3p1, OpenSSL 1.0.0-fips 29 Mar 2010 ? ? ? ? ? ? ? ?#第一階段,雙方確認協議版本號和ssh版本號 debug1: Reading configuration data /etc/ssh/ssh_config debug1: Applying options for * debug1: Connecting to 192.168.27.142 [192.168.27.142] port 22. debug1: Connection established. debug1: permanently_set_uid: 0/0 debug1: identity file /root/.ssh/identity type -1 debug1: identity file /root/.ssh/id_rsa type 1 debug1: identity file /root/.ssh/id_dsa type 2 debug1: Remote protocol version 2.0, remote software version OpenSSH_5.3 debug1: match: OpenSSH_5.3 pat OpenSSH* debug1: Enabling compatibility mode for protocol 2.0 debug1: Local version string SSH-2.0-OpenSSH_5.3 debug1: SSH2_MSG_KEXINIT sent ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?#第二階段,雙方確認/支持使用的數據加密算法,消息摘要算法,主機公鑰等信息. debug1: SSH2_MSG_KEXINIT received debug1: kex: server->client aes128-ctr hmac-md5 none debug1: kex: client->server aes128-ctr hmac-md5 none debug1: SSH2_MSG_KEX_DH_GEX_REQUEST(1024<1024<8192) sent debug1: expecting SSH2_MSG_KEX_DH_GEX_GROUP debug1: SSH2_MSG_KEX_DH_GEX_INIT sent debug1: expecting SSH2_MSG_KEX_DH_GEX_REPLY debug1: Host '192.168.27.142' is known and matches the RSA host key. debug1: Found key in /root/.ssh/known_hosts:1 debug1: ssh_rsa_verify: signature correct debug1: SSH2_MSG_NEWKEYS sent debug1: expecting SSH2_MSG_NEWKEYS debug1: SSH2_MSG_NEWKEYS received debug1: SSH2_MSG_SERVICE_REQUEST sent debug1: SSH2_MSG_SERVICE_ACCEPT received debug1: Authentications that can continue: gssapi-keyex,gssapi-with-mic,password,hostbased debug1: Next authentication method: password ? ? ? ? ? ? ? ? #第三階段,進入身份驗證的過程 root@192.168.27.142's password:? debug1: Authentication succeeded (password). debug1: channel 0: new [client-session] ? ? ? ? ? ? ? ? ? ? ?#第四階段,驗證成功后等到一個新的session,及設置環境變量等,最后得到一個shell. debug1: Requesting no-more-sessions@openssh.com debug1: Entering interactive session. debug1: Sending environment. debug1: Sending env LANG = en_US.UTF-8 Last login: Sun Jun 19 12:42:24 2011 from ssh-hacker 二)SSH服務端的各配置項 下面的試驗環境為: ssh client:192.168.27.143 ssh server:192.168.27.142 1)GSSAPI身份驗證. GSSAPIAuthentication 是否允許使用基于 GSSAPI 的用戶認證.默認值為"no".僅用于SSH-2. GSSAPICleanupCredentials 是否在用戶退出登錄后自動銷毀用戶憑證緩存。默認值是"yes".僅用于SSH-2. 注: GSSAPI是公共安全事務應用程序接口(GSS-API) 公共安全事務應用程序接口以一種統一的模式為使用者提供安全事務,由于它支持最基本的機制和技術,所以保證不同的應用環境下的可移植性. 該規范定義了GSS-API事務和基本元素,并獨立于基本的機制和程序設計語言環境,并借助于其它相關的文檔規范實現. 如果我們在服務端打開GSSAPIAuthentication配置項,如下: vi /etc/ssh/sshd_config # GSSAPI options GSSAPIAuthentication yes GSSAPICleanupCredentials yes 在客戶端登錄服務端會用gssapi-keyex,gssapi-with-mic進行身份校驗,同樣客戶端也要支持這種身份驗證,如下: vi /etc/ssh/ssh_config GSSAPIAuthentication yes GSSAPIDelegateCredentials yes 我們在客戶端連接SSH服務端,如下: ssh -v 192.168.27.142 OpenSSH_4.3p2 Debian-9, OpenSSL 0.9.8g 19 Oct 2007 debug1: Reading configuration data /etc/ssh/ssh_config debug1: Applying options for * debug1: Connecting to 192.168.27.142 [192.168.27.142] port 22. debug1: Connection established. debug1: identity file /home/chenkuo/.ssh/identity type -1 debug1: identity file /home/chenkuo/.ssh/id_rsa type -1 debug1: identity file /home/chenkuo/.ssh/id_dsa type -1 debug1: Remote protocol version 2.0, remote software version OpenSSH_4.3p2 Debian-9 debug1: match: OpenSSH_4.3p2 Debian-9 pat OpenSSH* debug1: Enabling compatibility mode for protocol 2.0 debug1: Local version string SSH-2.0-OpenSSH_4.3p2 Debian-9 debug1: Unspecified GSS failure. ?Minor code may provide more information No credentials cache found debug1: Unspecified GSS failure. ?Minor code may provide more information No credentials cache found debug1: Unspecified GSS failure. ?Minor code may provide more information No credentials cache found debug1: Unspecified GSS failure. ?Minor code may provide more information Unknown code H 1 debug1: SSH2_MSG_KEXINIT sent debug1: SSH2_MSG_KEXINIT received debug1: kex: server->client aes128-cbc hmac-md5 none debug1: kex: client->server aes128-cbc hmac-md5 none debug1: SSH2_MSG_KEX_DH_GEX_REQUEST(1024<1024<8192) sent debug1: expecting SSH2_MSG_KEX_DH_GEX_GROUP debug1: SSH2_MSG_KEX_DH_GEX_INIT sent debug1: expecting SSH2_MSG_KEX_DH_GEX_REPLY debug1: Host '192.168.27.142' is known and matches the RSA host key. debug1: Found key in /home/chenkuo/.ssh/known_hosts:1 debug1: ssh_rsa_verify: signature correct debug1: SSH2_MSG_NEWKEYS sent debug1: expecting SSH2_MSG_NEWKEYS debug1: SSH2_MSG_NEWKEYS received debug1: SSH2_MSG_SERVICE_REQUEST sent debug1: SSH2_MSG_SERVICE_ACCEPT received debug1: Authentications that can continue: publickey,gssapi-keyex,gssapi-with-mic,password debug1: Next authentication method: gssapi-keyex debug1: No valid Key exchange context debug1: Next authentication method: gssapi-with-mic debug1: Authentications that can continue: publickey,gssapi-keyex,gssapi-with-mic,password debug1: Authentications that can continue: publickey,gssapi-keyex,gssapi-with-mic,password debug1: Authentications that can continue: publickey,gssapi-keyex,gssapi-with-mic,password debug1: Authentications that can continue: publickey,gssapi-keyex,gssapi-with-mic,password 我們看到如下的信息: debug1: Unspecified GSS failure. ?Minor code may provide more information No credentials cache found debug1: Authentications that can continue: publickey,gssapi-keyex,gssapi-with-mic,password debug1: Next authentication method: gssapi-keyex debug1: No valid Key exchange context 說明SSH登錄時采用GSSAPI的方式進行身份驗證,但我們的系統不支持. 最后如果我們不用這種方式進行身份驗證的話,建議關閉這個選項,這樣可以提高驗證時的速度. 2)RSA/DSA密鑰認證 我們除了可以用UNIX密碼(unix passwd/shadow)方式登錄系統外,還可以選擇RSA/DSA密鑰認證方式登錄系統. 注: RSA:由RSA公司發明,是一個支持變長密鑰的公共密鑰算法,需要加密的文件塊的長度也是可變的; DSA(Digital Signature Algorithm):數字簽名算法,是一種標準的 DSS(數字簽名標準); 同時這兩種加密算法都是非對稱加密算法. 2.1)RSA密鑰認證試驗 首先用ssh-keygen生成一對RSA(公/私鑰),用ssh-copy-id將公鑰COPY到SSH服務端.最后登錄SSH服務端進行測試: 用rsa的認證方式生成公/私鑰,如下: ssh-keygen -t rsa? Generating public/private rsa key pair. Enter file in which to save the key (/home/chenkuo/.ssh/id_rsa):? Enter passphrase (empty for no passphrase):? Enter same passphrase again:? Your identification has been saved in /home/chenkuo/.ssh/id_rsa. Your public key has been saved in /home/chenkuo/.ssh/id_rsa.pub. The key fingerprint is: c3:8c:17:ad:95:cb:95:82:8b:eb:f1:a4:28:52:0e:f2 chenkuo@test2 用ssh-copy-id將id_rsa.pub(公鑰)COPY到SSH服務端,如下: ssh-copy-id -i .ssh/id_rsa.pub chenkuo@192.168.27.142 15 chenkuo@192.168.27.142's password:? Now try logging into the machine, with "ssh 'chenkuo@192.168.27.142'", and check in: .ssh/authorized_keys to make sure we haven't added extra keys that you weren't expecting. 再次登錄,我們發現,系統要求輸入id_rsa密碼,如下: ssh chenkuo@192.168.27.142 Enter passphrase for key '/home/chenkuo/.ssh/id_rsa':? Linux test2 2.6.18-4-k7 #1 SMP Mon Mar 26 17:57:15 UTC 2007 i686 The programs included with the Debian GNU/Linux system are free software; the exact distribution terms for each program are described in the individual files in /usr/share/doc/*/copyright. Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent permitted by applicable law. You have new mail. Last login: Sat May 28 19:19:32 2011 from 192.168.27.134 注: 事實上我們用ssh-keygen生成一只公鑰和私鑰,將公鑰轉到遠程待登錄的服務器,要用RSA登錄的時候,我們只要在本地的控制臺鍵入 ssh chenkuo@remotehost,就象我們常做的一樣. 可這一次,ssh 告訴 remotehost 的 sshd 它想使用 RSA 認證協議,接下來發生的事情非常有趣.Remotehost 的 sshd 會生成一個隨機數,并用我們先前拷貝過去的公鑰對這個隨機數進行加密. 然后,sshd 把加密了的隨機數發回給正在 clienthost 的 ssh客戶端程序.接下來,輪到我們的 ssh 用密鑰對這個隨機數進行解密后,再把它發回給 remotehost,實際上等于在說:瞧,我確實有匹配的專用密鑰,我能成功的對您的消息進行解密!" 最后,sshd 得出結論,既然我們持有匹配的專用密鑰,就應當允許我們登錄.因此,我們有匹配的專用密鑰這一事實授權我們訪問 remotehost. 服務端通過下面兩個選項來控制是否采用公/密鑰的方式進行身份驗證 PubkeyAuthentication yes #AuthorizedKeysFile ? ? %h/.ssh/authorized_keys 改成PubkeyAuthentication no則關閉公/私鑰認證 2.2)我們用類似的方法生成dsa公/私鑰. ssh-keygen -t dsa? Generating public/private dsa key pair. Enter file in which to save the key (/home/chenkuo/.ssh/id_dsa):? Enter passphrase (empty for no passphrase):? Enter same passphrase again:? Your identification has been saved in /home/chenkuo/.ssh/id_dsa. Your public key has been saved in /home/chenkuo/.ssh/id_dsa.pub. The key fingerprint is: 79:ea:d5:a8:49:7b:81:6c:17:d1:a4:43:f1:ac:29:29 chenkuo@test2 同樣將id_dsa.pub(公鑰)COPY到遠程服務器,如上: ssh-copy-id -i .ssh/id_dsa.pub chenkuo@192.168.27.142 15 chenkuo@192.168.27.142's password:? Now try logging into the machine, with "ssh 'chenkuo@192.168.27.142'", and check in: .ssh/authorized_keys to make sure we haven't added extra keys that you weren't expecting. 我們再次登錄,這里我們用ssh -v的方式打印更詳細的信息,如下: ssh -v chenkuo@192.168.27.142 OpenSSH_4.3p2 Debian-9, OpenSSL 0.9.8g 19 Oct 2007 debug1: Reading configuration data /etc/ssh/ssh_config debug1: Applying options for * debug1: Connecting to 192.168.27.142 [192.168.27.142] port 22. debug1: Connection established. debug1: identity file /home/chenkuo/.ssh/identity type -1 debug1: identity file /home/chenkuo/.ssh/id_rsa type -1 debug1: identity file /home/chenkuo/.ssh/id_dsa type 2 debug1: Remote protocol version 2.0, remote software version OpenSSH_4.3p2 Debian-9 debug1: match: OpenSSH_4.3p2 Debian-9 pat OpenSSH* debug1: Enabling compatibility mode for protocol 2.0 debug1: Local version string SSH-2.0-OpenSSH_4.3p2 Debian-9 debug1: SSH2_MSG_KEXINIT sent debug1: SSH2_MSG_KEXINIT received debug1: kex: server->client aes128-cbc hmac-md5 none debug1: kex: client->server aes128-cbc hmac-md5 none debug1: SSH2_MSG_KEX_DH_GEX_REQUEST(1024<1024<8192) sent debug1: expecting SSH2_MSG_KEX_DH_GEX_GROUP debug1: SSH2_MSG_KEX_DH_GEX_INIT sent debug1: expecting SSH2_MSG_KEX_DH_GEX_REPLY debug1: Host '192.168.27.142' is known and matches the RSA host key. debug1: Found key in /home/chenkuo/.ssh/known_hosts:1 debug1: ssh_rsa_verify: signature correct debug1: SSH2_MSG_NEWKEYS sent debug1: expecting SSH2_MSG_NEWKEYS debug1: SSH2_MSG_NEWKEYS received debug1: SSH2_MSG_SERVICE_REQUEST sent debug1: SSH2_MSG_SERVICE_ACCEPT received debug1: Authentications that can continue: publickey,password debug1: Next authentication method: publickey debug1: Trying private key: /home/chenkuo/.ssh/identity debug1: Trying private key: /home/chenkuo/.ssh/id_rsa debug1: Offering public key: /home/chenkuo/.ssh/id_dsa debug1: Server accepts key: pkalg ssh-dss blen 434 debug1: PEM_read_PrivateKey failed debug1: read PEM private key done: type <unknown> Enter passphrase for key '/home/chenkuo/.ssh/id_dsa':? debug1: read PEM private key done: type DSA debug1: Authentication succeeded (publickey). debug1: channel 0: new [client-session] debug1: Entering interactive session. debug1: Sending environment. debug1: Sending env LANG = en_US.UTF-8 Linux test2 2.6.18-4-k7 #1 SMP Mon Mar 26 17:57:15 UTC 2007 i686 The programs included with the Debian GNU/Linux system are free software; the exact distribution terms for each program are described in the individual files in /usr/share/doc/*/copyright. Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent permitted by applicable law. You have new mail. Last login: Sun May 29 05:21:04 2011 from 192.168.27.134 注: 如果要關閉用DSA公密鑰認證的方式,也要將PubkeyAuthentication改成no. 而DSA應用于ssh v2,而RSA在ssh v1上也得到支持. 另外我們可以在ssh配置文件中定義用于公/私鑰認證的公鑰文件物理位置,默認是: AuthorizedKeysFile ? ? ?.ssh/authorized_keys 如果采用RSA/DSA這種公/私鑰認證方式,我們建議這個采用默認配置,而不去更改它,因為ssh-copy-id等命令傳輸到被登錄服務器的公鑰文件就是~/.ssh/authorized_keys,例如: ssh-copy-id -i /root/.ssh/id_rsa.pub test@192.168.27.142 test@192.168.27.142's password:? Now try logging into the machine, with "ssh 'test@192.168.27.142'", and check in: .ssh/authorized_keys to make sure we haven't added extra keys that you weren't expecting. 3)關于免密碼的登入 在RSA/DSA生成密鑰對的時候,不輸入口令,直接回車,以這樣的密鑰對進行登錄,將不會提示用戶輸入密碼. 我們先生成RSA密鑰對,對下: ssh-keygen -t rsa Generating public/private rsa key pair. Enter file in which to save the key (/home/chenkuo/.ssh/id_rsa):? /home/chenkuo/.ssh/id_rsa already exists. Overwrite (y/n)? y Enter passphrase (empty for no passphrase): ? ? ? ? ? ? ?注意這里不要輸入密碼,直接回車通過? Enter same passphrase again: ? ? ? ? ? ? ? ? ? ? ? ? ? ? 同樣輸入回車 Your identification has been saved in /home/chenkuo/.ssh/id_rsa. Your public key has been saved in /home/chenkuo/.ssh/id_rsa.pub. The key fingerprint is: 27:f4:4d:61:5b:02:3f:d3:fc:a3:5b:d4:9b:08:81:64 chenkuo@test2 將id_rsa.pub傳輸到ssh服務端,如下: chenkuo@test2:~$ ssh-copy-id -i /home/chenkuo/.ssh/id_rsa.pub chenkuo@192.168.27.142 29 chenkuo@192.168.27.142's password:? Now try logging into the machine, with "ssh 'chenkuo@192.168.27.142'", and check in: .ssh/authorized_keys to make sure we haven't added extra keys that you weren't expecting. 再次登錄ssh服務端,這里不用輸入密碼,如下: ssh chenkuo@192.168.27.142 Linux test2 2.6.18-4-k7 #1 SMP Mon Mar 26 17:57:15 UTC 2007 i686 The programs included with the Debian GNU/Linux system are free software; the exact distribution terms for each program are described in the individual files in /usr/share/doc/*/copyright. Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent permitted by applicable law. You have new mail. Last login: Mon May 30 18:48:38 2011 from 192.168.27.134 chenkuo@test2:~$ 4)拒絕用UNIX/password的方式登錄系統 UNIX/password是傳統的認證方式,我們可以通過ssh配置參數拒絕以這種方式登錄服務器. 控制UNIX/password的登錄方式的配置選項是: PasswordAuthentication yes 默認是UNIX/password登錄方式是開啟的,如果關閉UNIX/password登錄方式將yes改成no即可,如下: vi /etc/ssh/sshd_config PasswordAuthentication no 存盤退出 重啟ssh服務: /etc/init.d/ssh restart 在客戶端再次登錄,發現沒有password登錄方式,如下: ssh -v chenkuo@192.168.27.142 OpenSSH_4.3p2 Debian-9, OpenSSL 0.9.8g 19 Oct 2007 debug1: Reading configuration data /etc/ssh/ssh_config debug1: Applying options for * debug1: Connecting to 192.168.27.142 [192.168.27.142] port 22. debug1: Connection established. debug1: identity file /home/chenkuo/.ssh/identity type -1 debug1: identity file /home/chenkuo/.ssh/id_rsa type 1 debug1: identity file /home/chenkuo/.ssh/id_dsa type 2 debug1: Remote protocol version 2.0, remote software version OpenSSH_4.3p2 Debian-9 debug1: match: OpenSSH_4.3p2 Debian-9 pat OpenSSH* debug1: Enabling compatibility mode for protocol 2.0 debug1: Local version string SSH-2.0-OpenSSH_4.3p2 Debian-9 debug1: SSH2_MSG_KEXINIT sent debug1: SSH2_MSG_KEXINIT received debug1: kex: server->client aes128-cbc hmac-md5 none debug1: kex: client->server aes128-cbc hmac-md5 none debug1: SSH2_MSG_KEX_DH_GEX_REQUEST(1024<1024<8192) sent debug1: expecting SSH2_MSG_KEX_DH_GEX_GROUP debug1: SSH2_MSG_KEX_DH_GEX_INIT sent debug1: expecting SSH2_MSG_KEX_DH_GEX_REPLY debug1: Host '192.168.27.142' is known and matches the RSA host key. debug1: Found key in /home/chenkuo/.ssh/known_hosts:1 debug1: ssh_rsa_verify: signature correct debug1: SSH2_MSG_NEWKEYS sent debug1: expecting SSH2_MSG_NEWKEYS debug1: SSH2_MSG_NEWKEYS received debug1: SSH2_MSG_SERVICE_REQUEST sent debug1: SSH2_MSG_SERVICE_ACCEPT received debug1: Authentications that can continue: publickey ? ? ? ?注意:這里沒有password的登錄方式了. debug1: Next authentication method: publickey debug1: Trying private key: /home/chenkuo/.ssh/identity debug1: Offering public key: /home/chenkuo/.ssh/id_rsa debug1: Authentications that can continue: publickey debug1: Offering public key: /home/chenkuo/.ssh/id_dsa debug1: Authentications that can continue: publickey debug1: No more authentication methods to try. Permission denied (publickey). 5)X11轉發 X11轉發允許在 SSH 客戶端上顯示應用程序的圖形部分,而程序邏輯依然在遠程服務器上執行.通過使用這種方法,用戶可以避免通過連接轉發整個桌面帶來的網絡開銷,并且僅接收到有關顯示部分的內容. 我們需要SSH客戶端有X服務器和SSH客戶端(如 Cygwin-X,XmanagerEnterprise或者是一個Xwindows),而SSH服務端要安裝ssh服務端以及任何要執行的x程序,如xclock或gnome-terminal等等. 我們ssh客戶端執行: ssh -X root@192.168.27.142 gnome-terminal 此時客戶端上會彈出一個gnome-terminal,在gnome-terminal執行命令其實就是在192.168.27.142(服務端)上執行. 注意: 服務端不一定要進入到x-windows里面,但它一定要有x客戶端程序. 而要完成上面的功能,我們就要保證X11Forwarding選項是yes,如下: X11Forwarding yes 如果是X11Forwarding選項是no,轉發X11程序則不會成功. 如果不需要這個功能,建議關閉該選項 6)SSH的日志級別 SSH有如下9個日志級別: QUIET, FATAL, ERROR, INFO, VERBOSE, DEBUG, DEBUG1, DEBUG2, and DEBUG3. 默認是INFO,DEBUG和DEBUG1是等價的,DEBUG級別一般用于調試. 我們將日志級別更改為VERBOSE,再用ssh客戶端連接服務端,查看服務端的ssh日志,看下INFO和VERBOSE的區別: 服務端: vi /etc/ssh/sshd_config LogLevel VERBOSE /etc/init.d/ssh restart 客戶端: ssh 192.168.27.143 The authenticity of host '192.168.27.143 (192.168.27.143)' can't be established. RSA key fingerprint is 49:35:e5:fe:1e:f4:cd:e2:50:d6:2e:57:35:cb:45:42. Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added '192.168.27.143' (RSA) to the list of known hosts. root@192.168.27.143's password:? Last login: Fri Jun ?3 06:49:50 2011 from 192.168.27.1 查看服務端的日志: tail -f /var/log/secure Jun ?3 07:57:58 localhost sshd[2242]: Connection from 192.168.27.143 port 52632 Jun ?3 07:58:00 localhost sshd[2242]: Accepted password for root from 192.168.27.143 port 52632 ssh2 Jun ?3 07:58:00 localhost sshd[2242]: pam_unix(sshd:session): session opened for user root by (uid=0) 將日志級別更改為INFO,將不會看到:Connection from 192.168.27.143 port 52632 如下: Jun ?3 07:57:03 localhost sshd[1787]: pam_unix(sshd:session): session closed for user root Jun ?3 07:57:07 localhost sshd[2202]: pam_unix(sshd:session): session opened for user root by (uid=0) 這里我們建議將日志級別調整為VERBOSE,這樣可以檢測對SSH服務的探測. 7)客戶端與服務端的環境變量傳遞 AcceptEnv指定客戶端發送的哪些環境變量將會被傳遞到會話環境中,但只有SSH-2協議支持環境變量的傳遞. 我們可以使用*和?做為通配符,例如: AcceptEnv LC* 這樣就可以接受所有以LC開頭的環境變量 默認是不傳遞任何環境變量. 若要支持環境變量傳遞,我們要在客戶端和服務端都要做相關的配置,例如我們要傳遞環境變量CMD,如下: 客戶端: 1)定義環境變量CMD declare -x CMD="hostname" 2)在ssh客戶端配置文件中增加發送環境變量的配置項,如下: vi /etc/ssh/ssh_config SendEnv CMD 存盤退出 服務端: 1)在ssh服務端配置文件sshd_config中增加接收環境變量的配置,如下: vi /etc/ssh/sshd_config AcceptEnv CMD 存盤退出 2)重啟ssh服務,如下: /etc/init.d/ssh restart 測試: ssh -v 192.168.27.142 OpenSSH_5.3p1, OpenSSL 1.0.0-fips 29 Mar 2010 debug1: Reading configuration data /etc/ssh/ssh_config debug1: Applying options for * debug1: Connecting to 192.168.27.142 [192.168.27.142] port 22. debug1: Connection established. debug1: permanently_set_uid: 0/0 debug1: identity file /root/.ssh/identity type -1 debug1: identity file /root/.ssh/id_rsa type -1 debug1: identity file /root/.ssh/id_dsa type -1 debug1: Remote protocol version 2.0, remote software version OpenSSH_5.3 debug1: match: OpenSSH_5.3 pat OpenSSH* debug1: Enabling compatibility mode for protocol 2.0 debug1: Local version string SSH-2.0-OpenSSH_5.3 debug1: SSH2_MSG_KEXINIT sent debug1: SSH2_MSG_KEXINIT received debug1: kex: server->client aes128-ctr hmac-md5 none debug1: kex: client->server aes128-ctr hmac-md5 none debug1: SSH2_MSG_KEX_DH_GEX_REQUEST(1024<1024<8192) sent debug1: expecting SSH2_MSG_KEX_DH_GEX_GROUP debug1: SSH2_MSG_KEX_DH_GEX_INIT sent debug1: expecting SSH2_MSG_KEX_DH_GEX_REPLY debug1: Host '192.168.27.142' is known and matches the RSA host key. debug1: Found key in /root/.ssh/known_hosts:1 debug1: ssh_rsa_verify: signature correct debug1: SSH2_MSG_NEWKEYS sent debug1: expecting SSH2_MSG_NEWKEYS debug1: SSH2_MSG_NEWKEYS received debug1: SSH2_MSG_SERVICE_REQUEST sent debug1: SSH2_MSG_SERVICE_ACCEPT received debug1: Authentications that can continue: publickey,gssapi-keyex,gssapi-with-mic,password debug1: Next authentication method: gssapi-with-mic debug1: An invalid name was supplied Cannot determine realm for numeric host address debug1: An invalid name was supplied Cannot determine realm for numeric host address debug1: An invalid name was supplied debug1: Next authentication method: publickey debug1: Trying private key: /root/.ssh/identity debug1: Trying private key: /root/.ssh/id_rsa debug1: Trying private key: /root/.ssh/id_dsa debug1: Next authentication method: password root@192.168.27.142's password:? debug1: Authentication succeeded (password). debug1: channel 0: new [client-session] debug1: Requesting no-more-sessions@openssh.com debug1: Entering interactive session. debug1: Sending environment. debug1: Sending env CMD = hostname ? ? ? ? ?/*注意這里ssh客戶端發送環境變量CMD給ssh服務端*/ debug1: Sending env LANG = en_US.UTF-8 Last login: Fri Jun ?3 22:32:56 2011 from 192.168.27.143 我們登錄到192.168.27.142(ssh服務端),查看環境變量是否傳遞成功,如下: echo $CMD hostname $CMD ssh-server 我們看到環境變量CMD已經傳遞成功. 但最后我們要補充說明的是,并不是所有的環境變量都會如我們所希望的那樣傳遞,比如PATH,原因是在ssh登錄的時候,系統也會做一些環境變量的設置,這時PATH會被改變,而不會是我們發送接受的變量. 8)AllowUsers/AllowGroups與DenyUsers/DenyGroups AllowUsers允許指定的用戶可以通過ssh服務登錄該服務器,如果使用了AllowUsers,則只有AllowUsers的用戶可以登錄服務器,其它用戶不能登錄服務器. 注意: 1)如果我們使用PermitRootLogin no(阻止Root用戶登錄),那樣AllowUsers root是不會生效的. 2)如果我們使用DenyUsers阻止某用戶登錄,而AllowUsers開放某用戶登錄,則以DenyUsers為準. 3)如果我們使用DenyGroups阻止某用戶組登錄,而AllowUsers開放某用戶登錄,也以DenyGroups為準. 4)如果增加多個用戶,各用戶名之間用空格分隔,例如:AllowUsers root test test1 最后我們對AllowUsers進行測試: ssh服務端: vi /etc/ssh/sshd_config AllowUsers test? 存盤退出,并重啟sshd服務 /etc/init.d/sshd restart ssh客戶端: 此時我們使用用戶test1登錄系統,發現無法登錄,如下: ssh ?test1@192.168.27.142 ?? test1@192.168.27.142's password:? Permission denied, please try again. 轉為使用test用戶,登錄成功,說明AllowUsers是起作用的,如下: ssh ?test@192.168.27.142 ? test@192.168.27.142's password:? Last login: Sat Jun ?4 18:50:52 2011 from 192.168.27.143 AllowGroups/DenyUsers/DenyGroups的用法都比較簡單,我們在此不一一舉例. 9)端口轉發 AllowTcpForwarding SSH有兩種端口轉發方式,分別是本地轉發和遠端轉發. 本地轉發: ssh本地轉發可以將連接本地端口的SOCKET數據轉發到遠程SSH服務端. 這是使用本地轉發的例子: 一臺SSH服務端提供ftp服務,因為ftp傳輸是明文密碼,如果不做ssh端口之前,我們可以通過tcpdump命令很容易的捕捉到明文信息. 所以我們要對21端口進行轉發: SSH客戶端: ssh -CNf -L 2001:localhost:21 root@192.168.27.142 root@192.168.27.142's password:? bind: Address already in use 注: -C 壓縮數據傳輸. -N 不執行腳本或命令.通常與-f連用. -f 后臺認證用戶/密碼,通常和-N連用,不用登錄到遠程主機. 我們在客戶端可以看到相應的端口如下: netstat -tnp ? Active Internet connections (w/o servers) Proto Recv-Q Send-Q Local Address ? ? ? ? ? ? ? Foreign Address ? ? ? ? ? ? State ? ? ? PID/Program name ?? tcp ? ? ? ?0 ? ? 52 192.168.27.143:22 ? ? ? ? ? 192.168.27.1:2275 ? ? ? ? ? ESTABLISHED 1520/0 ? ? ? ? ? ? ? tcp ? ? ? ?0 ? ? ?0 192.168.27.143:36373 ? ? ? ?192.168.27.142:22 ? ? ? ? ? ESTABLISHED 1547/ssh ? ? ? ? ? ? 注: 其中192.168.27.143:36373 ? ? ? ?192.168.27.142:22這一條就是SSH映射所產生的. 同時我們可以看到ssh映射的進程,如下: ps -ef|grep ssh avahi ? ? 1111 ? ? 1 ?0 11:37 ? ? ? ? ?00:00:00 avahi-daemon: running [ssh-client.local] root ? ? ?1280 ? ? 1 ?0 11:37 ? ? ? ? ?00:00:00 /usr/sbin/sshd root ? ? ?1520 ?1280 ?0 11:43 ? ? ? ? ?00:00:00 sshd: root@pts/0? root ? ? ?1547 ? ? 1 ?0 11:45 ? ? ? ? ?00:00:00 ssh -CNf -L 2001:localhost:21 root@192.168.27.142 root ? ? ?1554 ?1523 ?0 11:47 pts/0 ? ?00:00:00 grep ssh SSH服務端: netstat -tnp ? Active Internet connections (w/o servers) Proto Recv-Q Send-Q Local Address ? ? ? ? ? ? ? Foreign Address ? ? ? ? ? ? State ? ? ? PID/Program name ?? tcp ? ? ? ?0 ? ? ?0 192.168.27.142:22 ? ? ? ? ? 192.168.27.1:2990 ? ? ? ? ? ESTABLISHED 1708/0 ? ? ? ? ? ? ? tcp ? ? ? ?0 ? ? ?0 192.168.27.142:22 ? ? ? ? ? 192.168.27.143:51581 ? ? ? ?ESTABLISHED 1767/sshd: root? 注:我們看到192.168.27.142:22 ? ? ? ? ? 192.168.27.143:51581這一條就是SSH本地映射產生的. 此時我們在客戶端連接localhost的2001端口,ssh即將數據轉發到192.168.27.142(ssh服務端)的21端口,如下: [root@ssh-client ~]#ftp? ftp> open localhost 2001 Connected to localhost (127.0.0.1). 220 (vsFTPd 2.2.2) Name (localhost:root): test 331 Please specify the password. Password: 230 Login successful. Remote system type is UNIX. Using binary mode to transfer files. ftp>? 我們在服務端看到了監聽到的數據,如下: tcpdump -X -n -i eth1 'host 192.168.27.143' tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on eth1, link-type EN10MB (Ethernet), capture size 65535 bytes 20:35:56.392261 IP 192.168.27.1.mgcp-callagent > 192.168.27.143.ssh: Flags [P.], seq 1685371148:1685371200, ack 2463559151, win 15280, length 52 下面都是通過SSH加密后的數據,結果略. 而如果我們沒有使用SSH映射的方式進行FTP連接,則會產生明文數據(PASS.123456). 20:30:16.091389 IP 192.168.27.143.43867 > 192.168.27.142.ftp: Flags [P.], seq 11:24, ack 35, win 183, options [nop,nop,TS val 3656782 ecr 9909216], length 13 0x0000: ?4510 0041 a4de 4000 4006 dd5a c0a8 1b8f ?E..A..@.@..Z.... 0x0010: ?c0a8 1b8e ab5b 0015 40ff 06e5 551a 542c ?.....[..@...U.T, 0x0020: ?8018 00b7 0a07 0000 0101 080a 0037 cc4e ?.............7.N 0x0030: ?0097 33e0 5041 5353 2068 6974 6c65 720d ?..3.PASS.123456. 0x0040: ?0a ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? . 遠程轉發: 將遠程主機(服務器)的某個端口轉發到本地端指定機器的指定端口. 下面是一個遠程轉發的應用: 在SSH服務端執行下面遠程轉發的命令,其中192.168.27.143為ssh客戶端,如下: ssh -CNf -R 2001:localhost:21 root@192.168.27.143 此時由于ssh遠程轉發我們會有下面的端口,如下: netstat -tnp ? Active Internet connections (w/o servers) Proto Recv-Q Send-Q Local Address ? ? ? ? ? ? ? Foreign Address ? ? ? ? ? ? State ? ? ? PID/Program name ?? tcp ? ? ? ?0 ? ? ?0 192.168.27.142:48413 ? ? ? ?192.168.27.143:22 ? ? ? ? ? ESTABLISHED 1875/ssh ? ? ? ? ? ? tcp ? ? ? ?0 ? ? 52 192.168.27.142:22 ? ? ? ? ? 192.168.27.1:2279 ? ? ? ? ? ESTABLISHED 1714/0 ? ? ? ? ? ? ? 我們在客戶端上看下如下的端口: netstat -tulnp|grep 2001 tcp ? ? ? ?0 ? ? ?0 127.0.0.1:2001 ? ? ? ? ? ? ?0.0.0.0:* ? ? ? ? ? ? ? ? ? LISTEN ? ? ?1651/sshd: root ? ?? tcp ? ? ? ?0 ? ? ?0 ::1:2001 ? ? ? ? ? ? ? ? ? ?:::* ? ? ? ? ? ? ? ? ? ? ? ?LISTEN ? ? ?1651/sshd: root ? ?? 此時我們可以在客戶端上連接本地地址及端口,如下: [root@ssh-client ~]# ftp ? ? ? ?? ftp> open localhost 2001 Connected to localhost (127.0.0.1). 220 (vsFTPd 2.2.2) Name (localhost:root): test 331 Please specify the password. Password: 230 Login successful. Remote system type is UNIX. Using binary mode to transfer files. ftp>? 注: 我們可以選擇遠程端口轉發的方式來繞過防火墻. 最后我們言歸正轉,來看一下AllowTcpForwarding選項. 如果采用本地轉發方式,例如在客戶端執行:ssh -CNf -L 2001:localhost:21 root@192.168.27.142,此時服務端(192.168.27.142)如果AllowTcpForwarding選項是no,則不允許轉發. 如果采用遠程轉發方式,例如在服務端執行:ssh -CNf -R 2001:localhost:21 root@192.168.27.143,此時客戶端(192.168.27.143)如果AllowTcpForwarding選項是no,則不允許轉發. 10)遠程主機連接本地轉發端口 GatewayPorts是否允許遠程主機連接本地的轉發端口.默認值是"no". sshd 默認將遠程端口轉發綁定到loopback地址.這樣將阻止其它遠程主機連接到轉發端口。 GatewayPorts 指令可以讓 sshd 將遠程端口轉發綁定到非loopback地址,這樣就可以允許遠程主機連接了。 "no"表示僅允許本地連接,"yes"表示強制將遠程端口轉發綁定到統配地址(wildcard address), 這個配置項是要修改本地轉發機的ssh配置,如下: vi /etc/ssh/ssh_config GatewayPorts yes ssh -v -CNf -L 2001:192.168.27.142:22 root@192.168.27.143 /*注意:192.168.27.143為當前客戶端的IP,而192.168.27.142是遠程SSH服務端*/ OpenSSH_5.3p1, OpenSSL 1.0.0-fips 29 Mar 2010 debug1: Reading configuration data /etc/ssh/ssh_config debug1: Applying options for * debug1: Connecting to 192.168.27.143 [192.168.27.143] port 22. debug1: Connection established. debug1: permanently_set_uid: 0/0 debug1: identity file /root/.ssh/identity type -1 debug1: identity file /root/.ssh/id_rsa type 1 debug1: identity file /root/.ssh/id_dsa type 2 debug1: Remote protocol version 2.0, remote software version OpenSSH_5.3 debug1: match: OpenSSH_5.3 pat OpenSSH* debug1: Enabling compatibility mode for protocol 2.0 debug1: Local version string SSH-2.0-OpenSSH_5.3 debug1: SSH2_MSG_KEXINIT sent debug1: SSH2_MSG_KEXINIT received debug1: kex: server->client aes128-ctr hmac-md5 zlib@openssh.com debug1: kex: client->server aes128-ctr hmac-md5 zlib@openssh.com debug1: SSH2_MSG_KEX_DH_GEX_REQUEST(1024<1024<8192) sent debug1: expecting SSH2_MSG_KEX_DH_GEX_GROUP debug1: SSH2_MSG_KEX_DH_GEX_INIT sent debug1: expecting SSH2_MSG_KEX_DH_GEX_REPLY debug1: Host '192.168.27.143' is known and matches the RSA host key. debug1: Found key in /root/.ssh/known_hosts:2 debug1: ssh_rsa_verify: signature correct debug1: SSH2_MSG_NEWKEYS sent debug1: expecting SSH2_MSG_NEWKEYS debug1: SSH2_MSG_NEWKEYS received debug1: SSH2_MSG_SERVICE_REQUEST sent debug1: SSH2_MSG_SERVICE_ACCEPT received debug1: Authentications that can continue: publickey,gssapi-keyex,gssapi-with-mic,password,hostbased debug1: Next authentication method: publickey debug1: Trying private key: /root/.ssh/identity debug1: Offering public key: /root/.ssh/id_rsa debug1: Authentications that can continue: publickey,gssapi-keyex,gssapi-with-mic,password,hostbased debug1: Offering public key: /root/.ssh/id_dsa debug1: Authentications that can continue: publickey,gssapi-keyex,gssapi-with-mic,password,hostbased debug1: Next authentication method: password root@192.168.27.143's password:? debug1: Enabling compression at level 6. debug1: Authentication succeeded (password). debug1: Local connections to *:2001 forwarded to remote address 192.168.27.142:22 debug1: Local forwarding listening on 0.0.0.0 port 2001. debug1: channel 0: new [port listener] debug1: Local forwarding listening on :: port 2001. bind: Address already in use debug1: Requesting no-more-sessions@openssh.com debug1: Entering interactive session. 此時連接本地的eth1網卡地址: ssh -p 2001 192.168.27.143 debug1: Connection to port 2001 forwarding to 192.168.27.142 port 22 requested. debug1: channel 1: new [direct-tcpip] root@192.168.27.143's password:? Last login: Sat Jun 18 13:23:04 2011 from localhost.localdomain Welcome to _ ?_ | ||_| ? ? ? ? ? ? ? ?? | | _ ____ ?_ ? _ ?_ ?_? | || | ?_ \| | | |\ \/ / | || | | | | |_| |/ ? ?\ |_||_|_| |_|\____|\_/\_/ Linux support by <newhitler@163.com> My homepage: http://ckhitler.lupaworld.com [root@ssh-server ~]# exit logout Connection to 192.168.27.143 closed. [root@ssh-client ~]# debug1: channel 1: free: direct-tcpip: listening port 2001 for 192.168.27.142 port 22, connect from 192.168.27.143 port 43295, nchannels 2 注: 我們通過打開GatewayPorts選項,使用我們即可以用回環地址轉發,也可以用其它IP地址轉發,這樣就使我們可以通過ssh將該服務器做成一個轉發機. 我們關閉GatewayPorts選項后,只能使用本地連接,如下: vi /etc/ssh/ssh_config GatewayPorts no ssh -v -CNf -L 2001:192.168.27.142:22 root@192.168.27.143 OpenSSH_5.3p1, OpenSSL 1.0.0-fips 29 Mar 2010 debug1: Reading configuration data /etc/ssh/ssh_config debug1: Applying options for * debug1: Connecting to 192.168.27.143 [192.168.27.143] port 22. debug1: Connection established. debug1: permanently_set_uid: 0/0 debug1: identity file /root/.ssh/identity type -1 debug1: identity file /root/.ssh/id_rsa type 1 debug1: identity file /root/.ssh/id_dsa type 2 debug1: Remote protocol version 2.0, remote software version OpenSSH_5.3 debug1: match: OpenSSH_5.3 pat OpenSSH* debug1: Enabling compatibility mode for protocol 2.0 debug1: Local version string SSH-2.0-OpenSSH_5.3 debug1: SSH2_MSG_KEXINIT sent debug1: SSH2_MSG_KEXINIT received debug1: kex: server->client aes128-ctr hmac-md5 zlib@openssh.com debug1: kex: client->server aes128-ctr hmac-md5 zlib@openssh.com debug1: SSH2_MSG_KEX_DH_GEX_REQUEST(1024<1024<8192) sent debug1: expecting SSH2_MSG_KEX_DH_GEX_GROUP debug1: SSH2_MSG_KEX_DH_GEX_INIT sent debug1: expecting SSH2_MSG_KEX_DH_GEX_REPLY debug1: Host '192.168.27.143' is known and matches the RSA host key. debug1: Found key in /root/.ssh/known_hosts:2 debug1: ssh_rsa_verify: signature correct debug1: SSH2_MSG_NEWKEYS sent debug1: expecting SSH2_MSG_NEWKEYS debug1: SSH2_MSG_NEWKEYS received debug1: SSH2_MSG_SERVICE_REQUEST sent debug1: SSH2_MSG_SERVICE_ACCEPT received debug1: Authentications that can continue: publickey,gssapi-keyex,gssapi-with-mic,password,hostbased debug1: Next authentication method: publickey debug1: Trying private key: /root/.ssh/identity debug1: Offering public key: /root/.ssh/id_rsa debug1: Authentications that can continue: publickey,gssapi-keyex,gssapi-with-mic,password,hostbased debug1: Offering public key: /root/.ssh/id_dsa debug1: Authentications that can continue: publickey,gssapi-keyex,gssapi-with-mic,password,hostbased debug1: Next authentication method: password root@192.168.27.143's password:? debug1: Authentications that can continue: publickey,gssapi-keyex,gssapi-with-mic,password,hostbased? debug1: Enabling compression at level 6. debug1: Authentication succeeded (password). debug1: Local connections to LOCALHOST:2001 forwarded to remote address 192.168.27.142:22 /*我們看到這里只做了將本地localhost:2001轉發到192.168.27.142:22*/ debug1: Local forwarding listening on ::1 port 2001. debug1: channel 0: new [port listener] debug1: Local forwarding listening on 127.0.0.1 port 2001. debug1: channel 1: new [port listener] debug1: Requesting no-more-sessions@openssh.com [root@ssh-client ~]# debug1: Entering interactive session. 11)登錄時顯示的信息 有如下的選項可以控制登錄ssh時顯示的信息 11.1)Banner Banner用于在登錄之前顯示在用戶屏幕上,如果定義為none,則不顯示任何信息,我們可以指定Banner為相應的文件,如下: Banner /etc/issue cat /etc/issue ############################################################################# # ? ? ? Warning: Unauthorized access to this system is strictly prohibited. # # ? ? ? Use of this system is limited to authorized individuals only. ? ? ? # # ? ? ? All activities are monitored. ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? # ############################################################################# 這樣在我們登錄的時候,可以看到/etc/issue中的信息,如下: ssh 192.168.27.142 ? ? ? ############################################################################# # ? ? ? Warning: Unauthorized access to this system is strictly prohibited. # # ? ? ? Use of this system is limited to authorized individuals only. ? ? ? # # ? ? ? All activities are monitored. ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? # ############################################################################# root@192.168.27.142's password:? 11.2)PrintLastLog PrintLastLog用于顯示在每一次成功登錄后顯示最后一位用戶的登錄信息,如下: PrintLastLog yes ssh 192.168.27.142 root@192.168.27.142's password:? Last login: Mon Jun ?6 14:23:24 2011 from 192.168.27.143 11.3)PrintMotd PrintMotd用于顯示在每一次成功登錄后顯示/etc/motd中的信息,如下: cat /etc/motd Welcome to _ ?_ | ||_| ? ? ? ? ? ? ? ?? | | _ ____ ?_ ? _ ?_ ?_? | || | ?_ \| | | |\ \/ / | || | | | | |_| |/ ? ?\ |_||_|_| |_|\____|\_/\_/ Linux support by <newhitler@163.com> My homepage: http://ckhitler.lupaworld.com ssh 192.168.27.142 root@192.168.27.142's password:? Welcome to _ ?_ | ||_| ? ? ? ? ? ? ? ?? | | _ ____ ?_ ? _ ?_ ?_? | || | ?_ \| | | |\ \/ / | || | | | | |_| |/ ? ?\ |_||_|_| |_|\____|\_/\_/ Linux support by <newhitler@163.com> My homepage: http://ckhitler.lupaworld.com 11.4)ShowPatchLevel ShowPatchLevel用于在連接ssh端口時,是否返回SSH的補丁版本信息,如下: telnet 192.168.27.142 22 Trying 192.168.27.142... Connected to 192.168.27.142. Escape character is '^]'. SSH-2.0-OpenSSH_5.3p1-FC-0.9-20.el6 ^] telnet> quit Connection closed. 以上是指定ShowPatchLevel yes的結果. [root@ssh-client ~]# telnet 192.168.27.142 22 Trying 192.168.27.142... Connected to 192.168.27.142. Escape character is '^]'. SSH-2.0-OpenSSH_5.3 ^] telnet> quit Connection closed. 以上是指定ShowPatchLevel no的結果. 我們建議如下的設置: Banner /etc/issue,/etc/issue放入警告信息. PrintMotd yes,在/etc/motd放入登錄后的歡迎信息. ShowPatchLevel no,不顯示ssh的補丁信息. PrintLastLog no,不顯示最后一次的登錄信息. 12)數據加密算法 我們可以通過Ciphers配置項來選擇數據加密算法,如果服務端僅支持aes128-cbc,而客戶端指定用arcfour加密算法連接登錄服務端則不會成功. sshv2支持如下的加密算法,相同默認值也是如下的算法: aes128-cbc,aes192-cbc,aes256-cbc,aes128-ctr,aes192-ctr,aes256-ctr,3des-cbc,arcfour128,arcfour256,arcfour,blowfish-cbc,cast128-cbc 上面的這些算法都是對稱加密算法,而arcfour是最快的,這里的arcfour算法也就是rc4. 下面是arcfour(rc4)對稱加密算法的說明: 會話密鑰的前16個字節被服務器用作加密密鑰,緊接著的下一個16字節被客戶端用作加密密鑰.結果是兩個數據流方向上有兩個獨立的129位密鑰.這種加密算法非常快 我們可以通過openssl speed對加密算法進行測試,也可以指定幾種加密算法進行測試,如下: openssl speed aes rc4 blowfish Doing rc4 for 3s on 16 size blocks: 40757592 rc4's in 1.28s Doing rc4 for 3s on 64 size blocks: 11500211 rc4's in 1.23s Doing rc4 for 3s on 256 size blocks: 2994613 rc4's in 1.45s Doing rc4 for 3s on 1024 size blocks: 770815 rc4's in 1.50s Doing rc4 for 3s on 8192 size blocks: 97511 rc4's in 1.37s Doing aes-128 cbc for 3s on 16 size blocks: 7294501 aes-128 cbc's in 1.39s Doing aes-128 cbc for 3s on 64 size blocks: 1996086 aes-128 cbc's in 1.30s Doing aes-128 cbc for 3s on 256 size blocks: 514051 aes-128 cbc's in 1.32s Doing aes-128 cbc for 3s on 1024 size blocks: 314747 aes-128 cbc's in 1.32s Doing aes-128 cbc for 3s on 8192 size blocks: 39487 aes-128 cbc's in 1.33s Doing aes-192 cbc for 3s on 16 size blocks: 6322661 aes-192 cbc's in 1.36s Doing aes-192 cbc for 3s on 64 size blocks: 1709890 aes-192 cbc's in 1.29s Doing aes-192 cbc for 3s on 256 size blocks: 431680 aes-192 cbc's in 1.39s Doing aes-192 cbc for 3s on 1024 size blocks: 271721 aes-192 cbc's in 1.37s Doing aes-192 cbc for 3s on 8192 size blocks: 32095 aes-192 cbc's in 1.54s Doing aes-256 cbc for 3s on 16 size blocks: 5116714 aes-256 cbc's in 1.49s Doing aes-256 cbc for 3s on 64 size blocks: 1406771 aes-256 cbc's in 1.43s Doing aes-256 cbc for 3s on 256 size blocks: 350117 aes-256 cbc's in 1.61s Doing aes-256 cbc for 3s on 1024 size blocks: 215622 aes-256 cbc's in 1.51s Doing aes-256 cbc for 3s on 8192 size blocks: 28925 aes-256 cbc's in 1.47s Doing blowfish cbc for 3s on 16 size blocks: 14535384 blowfish cbc's in 1.41s Doing blowfish cbc for 3s on 64 size blocks: 3924785 blowfish cbc's in 1.27s Doing blowfish cbc for 3s on 256 size blocks: 993143 blowfish cbc's in 1.34s Doing blowfish cbc for 3s on 1024 size blocks: 248679 blowfish cbc's in 1.34s Doing blowfish cbc for 3s on 8192 size blocks: 30867 blowfish cbc's in 1.46s OpenSSL 1.0.0-fips 29 Mar 2010 built on: Wed Jun 30 08:58:02 EDT 2010 options:bn(64,32) md2(int) rc4(4x,int) des(ptr,risc1,16,long) aes(partial) blowfish(idx)? compiler: gcc -fPIC -DOPENSSL_PIC -DZLIB -DOPENSSL_THREADS -D_REENTRANT -DDSO_DLFCN -DHAVE_DLFCN_H -DKRB5_MIT -DL_ENDIAN -DTERMIO -Wall -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m32 -march=i686 -mtune=atom -fasynchronous-unwind-tables -Wa,--noexecstack -DOPENSSL_BN_ASM_PART_WORDS -DOPENSSL_IA32_SSE2 -DOPENSSL_BN_ASM_MONT -DSHA1_ASM -DSHA256_ASM -DSHA512_ASM -DMD5_ASM -DRMD160_ASM -DAES_ASM -DWHIRLPOOL_ASM The 'numbers' are in 1000s of bytes per second processed. type ? ? ? ? ? ? 16 bytes ? ? 64 bytes ? ?256 bytes ? 1024 bytes ? 8192 bytes rc4 ? ? ? ? ? ? 509469.90k ? 598384.96k ? 528704.09k ? 526209.71k ? 583073.07k blowfish cbc ? ?164940.53k ? 197784.44k ? 189734.78k ? 190035.30k ? 173193.47k aes-128 cbc ? ? ?83965.48k ? ?98268.85k ? ?99694.74k ? 244167.37k ? 243216.17k aes-192 cbc ? ? ?74384.25k ? ?84831.75k ? ?79503.65k ? 203096.57k ? 170728.73k aes-256 cbc ? ? ?54944.58k ? ?62960.38k ? ?55670.78k ? 146223.13k ? 161192.93k 我們生成一個100MB的數據文件進行測試,如下: dd if=/dev/zero of=/tmp/bigfile.dat bs=1M count=100; shred -v -n3 /tmp/bigfile.dat 我們指定用arcfour對稱加密算法進行加密傳輸,這里用了2分10秒 rsync -apur --stats --progress -e "ssh -c arcfour" bigfile.dat root@192.168.27.142:/tmp/ ? ? ? root@192.168.27.142's password:? sending incremental file list bigfile.dat 1048576000 100% ? ?7.66MB/s ? ?0:02:10 (xfer#1, to-check=0/1) Number of files: 1 Number of files transferred: 1 Total file size: 1048576000 bytes Total transferred file size: 1048576000 bytes Literal data: 1048576000 bytes Matched data: 0 bytes File list size: 28 File list generation time: 0.001 seconds File list transfer time: 0.000 seconds Total bytes sent: 1048704076 Total bytes received: 31 sent 1048704076 bytes ?received 31 bytes ?7464086.17 bytes/sec total size is 1048576000 ?speedup is 1.00 我們指定用blowfish-cbc對稱加密算法進行加密傳輸,這里用了2分17秒 rsync -apur --stats --progress -e "ssh -c blowfish-cbc" bigfile.dat root@192.168.27.142:/tmp/? root@192.168.27.142's password:? sending incremental file list bigfile.dat 1048576000 100% ? ?7.26MB/s ? ?0:02:17 (xfer#1, to-check=0/1) Number of files: 1 Number of files transferred: 1 Total file size: 1048576000 bytes Total transferred file size: 1048576000 bytes Literal data: 1048576000 bytes Matched data: 0 bytes File list size: 28 File list generation time: 0.001 seconds File list transfer time: 0.000 seconds Total bytes sent: 1048704076 Total bytes received: 31 sent 1048704076 bytes ?received 31 bytes ?7464086.17 bytes/sec total size is 1048576000 ?speedup is 1.00 我們指定用aes128-ctr對稱加密算法進行加密傳輸,這里用了2秒55秒 rsync -apur --stats --progress -e "ssh -c aes128-ctr" bigfile.dat root@192.168.27.142:/tmp/? root@192.168.27.142's password:? sending incremental file list bigfile.dat 1048576000 100% ? ?5.71MB/s ? ?0:02:55 (xfer#1, to-check=0/1) Number of files: 1 Number of files transferred: 1 Total file size: 1048576000 bytes Total transferred file size: 1048576000 bytes Literal data: 1048576000 bytes Matched data: 0 bytes File list size: 28 File list generation time: 0.003 seconds File list transfer time: 0.000 seconds Total bytes sent: 1048704076 Total bytes received: 31 sent 1048704076 bytes ?received 31 bytes ?5941666.33 bytes/sec total size is 1048576000 ?speedup is 1.00 注: 1)如果我們沒有指Ciphers,將支持所有的加密算法,而客戶端沒有指定加密算法的話,我們首先使用的將是aes128-ctr對稱加密算法. 2)如果我們在服務端同時指定Ciphers arcfour,blowfish-cbc,aes128-ctr,而優先使用aes128-ctr其次是blowfish-cbc,最后是arcfour. 最后我們建議在服務端的ciphers選項上僅指定arcfour算法.這樣能最優化的進行數據加密傳輸. 13)使用login程序登錄 UseLogin默認值是"no",如果指定UseLogin為yes,我們將在登錄的過程中使用ssh服務端的login程序進行登錄驗證. 我們對使用login程序進行測試如下: 將UseLogin修改為yes,如下: vi /etc/ssh/sshd_config UseLogin yes 保存退出 重啟sshd服務 /etc/init.d/sshdrestart 用客戶端連接sshd服務端,如下: ssh ?192.168.27.142? 查看是否使用login程序,如下: ps -ef|grep login test ? ? ?1717 ? ? 1 ?0 03:59 ? ? ? ? ?00:00:00 /usr/bin/gnome-keyring-daemon --daemonize --login root ? ? ?2711 ?2709 ?0 05:25 ? ? ? ? ?00:00:00 login -- root ? ? ? ? ? ? ? ? ? ? ? ? root ? ? ?2732 ?2712 ?0 05:25 pts/2 ? ?00:00:00 grep login 注:如果將login程序移走或刪除,我們如果使用UseLogin yes,此時將無法登錄ssh服務端. 我們可以使用pam(基于Linux的插入式驗證模塊)加入一些login的認證功能. 我們在/etc/pam.d/remote文件中加入pam_access.so模塊,如下: vi /etc/pam.d/remote account ? ?required ? ? pam_access.so 保存退出 修改/etc/security/access.conf文件,如下: vi /etc/security/access.conf? 加入: - : ALL : ALL 保存退出.? 注: 現在我們拒絕所有通過ssh客戶端的連接,但我們沒有修改/etc/pam.d/login,所以我們本地我們還可以用login進行登錄. 通過ssh客戶端連接報錯如下: [root@ssh-client ~]# ssh ?192.168.27.142? root@192.168.27.142's password:? Permission denied Connection to 192.168.27.142 closed. 14)超時斷開 可以通過ClientAliveCountMax和ClientAliveInterval兩個選項控制客戶端在無響應的情況下斷開連接. ClientAliveCountMax: sshd在未收到任何客戶端回應前最多允許發送多少個"alive"消息,到達這個上限后,sshd 將強制斷開連接,關閉會話. 注: 需要注意的是,"alive"消息與TCPKeepAlive有很大差異.alive"消息是通過加密連接發送的,因此不會被欺騙,而TCPKeepAlive卻是可以被欺騙的. 如果ClientAliveInterval被設為15并且將ClientAliveCountMax保持為默認值(3),那么無應答的客戶端大約會在45秒后被強制斷開.這個指令僅可以用于SSH-2協議. ClientAliveInterval: 設置一個以秒記的時長,如果超過這么長時間沒有收到客戶端的任何數據,sshd 將通過安全通道向客戶端發送一個"alive"消息,并等候應答. 默認值0表示不發送"alive"消息.這個選項僅對SSH-2有效. 我們通過試驗來測試超時斷開的情況,如下: vi /etc/ssh/sshd_config ClientAliveCountMax 10 ClientAliveInterval 1 我們通過客戶端連接SSH服務端,此時服務端向客戶端發送alive消息,而客戶端回應reply消息給服務端,發送的頻率是每秒發送一次,如果沒有響應則超過(10*1)秒后斷開,如下: [root@ssh-client ~]# ssh ?-v 192.168.27.142 登錄信息略... [root@ssh-server ~]#? debug1: client_input_channel_req: channel 0 rtype keepalive@openssh.com reply 1 debug1: client_input_channel_req: channel 0 rtype keepalive@openssh.com reply 1 debug1: client_input_channel_req: channel 0 rtype keepalive@openssh.com reply 1 debug1: client_input_channel_req: channel 0 rtype keepalive@openssh.com reply 1 debug1: client_input_channel_req: channel 0 rtype keepalive@openssh.com reply 1 debug1: client_input_channel_req: channel 0 rtype keepalive@openssh.com reply 1 debug1: client_input_channel_req: channel 0 rtype keepalive@openssh.com reply 1 我們斷開client端的網卡,如下: [root@ssh-client ~]# ifconfig eth1 down? 此時服務端繼續發送alive消息,而客戶端由于斷開,所以沒有reply消息,所以我在剛才的登錄終端再也看不到reply消息,我們可以通過tcpdump抓包來證實,如下: [root@ssh-server ~]# tcpdump -i eth1 'port 22 and host 192.168.27.143' 此時客戶端沒有斷開,所以服務端與客戶端和3次握手的交互,如下: 19:40:46.677914 IP ssh-server.ssh > 192.168.27.143.45105: Flags [P.], seq 2910:2974, ack 2422, win 478, options [nop,nop,TS val 9540813 ecr 9291132], length 64 19:40:46.678596 IP 192.168.27.143.45105 > ssh-server.ssh: Flags [P.], seq 2422:2454, ack 2974, win 379, options [nop,nop,TS val 9292137 ecr 9540813], length 32 19:40:46.678640 IP ssh-server.ssh > 192.168.27.143.45105: Flags [.], ack 2454, win 478, options [nop,nop,TS val 9540814 ecr 9292137], length 0 19:40:47.681213 IP ssh-server.ssh > 192.168.27.143.45105: Flags [P.], seq 2974:3038, ack 2454, win 478, options [nop,nop,TS val 9541816 ecr 9292137], length 64 19:40:47.682130 IP 192.168.27.143.45105 > ssh-server.ssh: Flags [P.], seq 2454:2486, ack 3038, win 379, options [nop,nop,TS val 9293140 ecr 9541816], length 32 19:40:47.682167 IP ssh-server.ssh > 192.168.27.143.45105: Flags [.], ack 2486, win 478, options [nop,nop,TS val 9541817 ecr 9293140], length 0 19:40:48.685266 IP ssh-server.ssh > 192.168.27.143.45105: Flags [P.], seq 3038:3102, ack 2486, win 478, options [nop,nop,TS val 9542820 ecr 9293140], length 64 19:40:48.685863 IP 192.168.27.143.45105 > ssh-server.ssh: Flags [P.], seq 2486:2518, ack 3102, win 379, options [nop,nop,TS val 9294144 ecr 9542820], length 32 19:40:48.685911 IP ssh-server.ssh > 192.168.27.143.45105: Flags [.], ack 2518, win 478, options [nop,nop,TS val 9542821 ecr 9294144], length 0 19:40:49.690680 IP ssh-server.ssh > 192.168.27.143.45105: Flags [P.], seq 3102:3166, ack 2518, win 478, options [nop,nop,TS val 9543826 ecr 9294144], length 64 19:40:49.691261 IP 192.168.27.143.45105 > ssh-server.ssh: Flags [P.], seq 2518:2550, ack 3166, win 379, options [nop,nop,TS val 9295149 ecr 9543826], length 32 19:40:49.691311 IP ssh-server.ssh > 192.168.27.143.45105: Flags [.], ack 2550, win 478, options [nop,nop,TS val 9543826 ecr 9295149], length 0 此時客戶端已經斷開,所以只有服務端的發送消息,沒有客戶端回應的消息,如下: 19:40:50.698084 IP ssh-server.ssh > 192.168.27.143.45105: Flags [P.], seq 3166:3230, ack 2550, win 478, options [nop,nop,TS val 9544833 ecr 9295149], length 64 19:40:50.902427 IP ssh-server.ssh > 192.168.27.143.45105: Flags [P.], seq 3166:3230, ack 2550, win 478, options [nop,nop,TS val 9545037 ecr 9295149], length 64 19:40:51.311739 IP ssh-server.ssh > 192.168.27.143.45105: Flags [P.], seq 3166:3230, ack 2550, win 478, options [nop,nop,TS val 9545447 ecr 9295149], length 64 19:40:52.128414 IP ssh-server.ssh > 192.168.27.143.45105: Flags [P.], seq 3166:3230, ack 2550, win 478, options [nop,nop,TS val 9546263 ecr 9295149], length 64 19:40:53.763202 IP ssh-server.ssh > 192.168.27.143.45105: Flags [P.], seq 3166:3230, ack 2550, win 478, options [nop,nop,TS val 9547898 ecr 9295149], length 64 19:40:57.028357 IP ssh-server.ssh > 192.168.27.143.45105: Flags [P.], seq 3166:3230, ack 2550, win 478, options [nop,nop,TS val 9551163 ecr 9295149], length 64 19:41:00.749900 IP ssh-server.ssh > 192.168.27.143.45105: Flags [FP.], seq 3230:3806, ack 2550, win 478, options [nop,nop,TS val 9554885 ecr 9295149], length 576 19:41:03.559115 IP ssh-server.ssh > 192.168.27.143.45105: Flags [FP.], seq 3166:3806, ack 2550, win 478, options [nop,nop,TS val 9557694 ecr 9295149], length 640 19:41:16.616455 IP ssh-server.ssh > 192.168.27.143.45105: Flags [FP.], seq 3166:3806, ack 2550, win 478, options [nop,nop,TS val 9570751 ecr 9295149], length 640 19:41:42.729343 IP ssh-server.ssh > 192.168.27.143.45105: Flags [FP.], seq 3166:3806, ack 2550, win 478, options [nop,nop,TS val 9596864 ecr 9295149], length 640 最后我們看到服務端向客戶端發送alive消息,客戶端沒有響應,服務端再不發送消息,此時客戶端已經被認定斷開. 這里我們注意,斷開后服務端不會一直向客戶端發送消息,在發送了幾次消息之后,客戶端無響應,此時服務端將不會發送消息,直到等ClientAliveCountMax*ClientAliveInterval秒后斷開. 我們開啟client端的網卡,如下: [root@ssh-client ~]# ifconfig eth1 up 此時客戶端連接服務端的ssh終端表現如下: [root@ssh-server ~]# debug1: client_input_channel_req: channel 0 rtype keepalive@openssh.com reply 1 debug1: client_input_channel_req: channel 0 rtype keepalive@openssh.com reply 1 debug1: client_input_channel_req: channel 0 rtype keepalive@openssh.com reply 1 debug1: client_input_channel_req: channel 0 rtype keepalive@openssh.com reply 1 debug1: client_input_channel_req: channel 0 rtype keepalive@openssh.com reply 1 debug1: client_input_channel_req: channel 0 rtype keepalive@openssh.com reply 1 debug1: client_input_channel_req: channel 0 rtype keepalive@openssh.com reply 1 debug1: client_input_channel_req: channel 0 rtype keepalive@openssh.com reply 1 debug1: client_input_channel_req: channel 0 rtype keepalive@openssh.com reply 1 debug1: client_input_channel_req: channel 0 rtype keepalive@openssh.com reply 1 debug1: client_input_channel_req: channel 0 rtype keepalive@openssh.com reply 1 Write failed: Broken pipe 注: 開啟網卡后,但是已經超過了斷開的限制,客戶端已經斷開,我們按回車后終端顯示:Write failed: Broken pipe 最后ssh服務端向被認定已經斷開的客戶端發送斷開的命令,我們回到剛才的tcpdump抓包終端,顯示如下: 19:44:48.757691 IP ssh-server.ssh > 192.168.27.143.45105: Flags [R], seq 3345246483, win 0, length 0 我們再來說明一下默認的配置: clientaliveinterval 0 clientalivecountmax 3 在這種情況下,我們視為ssh服務端為長連接,在這種情況上,客戶端連接上后,服務端不再發送alive消息.如果客戶端斷開,服務端一直等待客戶端的連接,不會主動斷開. 同時我們也可以在客戶端配置監測服務端的斷開狀態,如下: vi /etc/ssh/ssh_config ServerAliveCountMax 100 ServerAliveInterval 1 此時如果服務端斷開,客戶端將向服務端發送alive消息,判斷服務端的狀態.如果服務端斷開,客戶端將在ServerAliveCountMax*ServerAliveInterval秒后斷開連接. 斷開消息如下: Timeout, server not responding. 我們建議如下的配置: 服務端: clientaliveinterval 300 clientalivecountmax 2 這樣我們300秒向客戶端發送一次alive信息,在600秒內客戶端沒有響應,客戶端被斷開,并且服務端清理客戶端的連接. 客戶端: serveraliveinterval 300 serveralivecountmax 2 同時將客戶端/服務端的tcpkeepalive選項關閉: tcpkeepalive no 15)host-based驗證 我們這里看到了另外一種驗證(此前我們接觸了password,rsa/dsa,GSSAPI等三種驗證方式),這種驗證方式基于主機名和公/私鑰. 其中host-based驗證是基于ssh-v2 首先我們要在客戶端/服務端加入對方的主機名及IP對映,如下: 服務端: vi /etc/hosts 192.168.27.142 ?ssh-server ? ? ?# Added by NetworkManager 192.168.27.143 ?ssh-client ? ? ?# Added by NetworkManager 客戶端: vi /etc/hosts 192.168.27.142 ?ssh-server ? ? ?# Added by NetworkManager 192.168.27.143 ?ssh-client ? ? ?# Added by NetworkManager 修改服務端的ssh配置,如下: vi /etc/ssh/sshd_config #打開host_based的驗證 HostbasedAuthentication yes #不允許忽略~/.ssh/known_hosts IgnoreUserKnownHosts no #不允許忽略~/.shosts IgnoreRhosts no 在服務端生成客戶主機的密鑰對,如下: ssh-keyscan -t rsa,dsa ssh-client > ~/.ssh/known_hosts 將客戶端主機名寫入到用戶主目錄的.shosts文件中 vi ~/.shosts ssh-client 重啟ssh服務端,如下: /etc/init.d/sshd restart 在客戶端修改ssh配置,如下: vi /etc/ssh/ssh_config #打開客戶端的host_based驗證 HostbasedAuthentication yes EnableSSHKeysign yes 我們在客戶端登錄SSH服務端,如下: ssh -v 192.168.27.142 OpenSSH_5.3p1, OpenSSL 1.0.0-fips 29 Mar 2010 debug1: Reading configuration data /etc/ssh/ssh_config debug1: Applying options for * debug1: Connecting to 192.168.27.142 [192.168.27.142] port 22. debug1: Connection established. debug1: read PEM private key done: type DSA debug1: read PEM private key done: type RSA debug1: permanently_set_uid: 0/0 debug1: identity file /root/.ssh/identity type -1 debug1: identity file /root/.ssh/id_rsa type 1 debug1: identity file /root/.ssh/id_dsa type -1 debug1: Remote protocol version 2.0, remote software version OpenSSH_5.3 debug1: match: OpenSSH_5.3 pat OpenSSH* debug1: Enabling compatibility mode for protocol 2.0 debug1: Local version string SSH-2.0-OpenSSH_5.3 debug1: SSH2_MSG_KEXINIT sent debug1: SSH2_MSG_KEXINIT received debug1: kex: server->client aes128-ctr hmac-md5 none debug1: kex: client->server aes128-ctr hmac-md5 none debug1: SSH2_MSG_KEX_DH_GEX_REQUEST(1024<1024<8192) sent debug1: expecting SSH2_MSG_KEX_DH_GEX_GROUP debug1: SSH2_MSG_KEX_DH_GEX_INIT sent debug1: expecting SSH2_MSG_KEX_DH_GEX_REPLY debug1: Host '192.168.27.142' is known and matches the RSA host key. debug1: Found key in /root/.ssh/known_hosts:1 debug1: ssh_rsa_verify: signature correct debug1: SSH2_MSG_NEWKEYS sent debug1: expecting SSH2_MSG_NEWKEYS debug1: SSH2_MSG_NEWKEYS received debug1: SSH2_MSG_SERVICE_REQUEST sent debug1: SSH2_MSG_SERVICE_ACCEPT received debug1: Authentications that can continue: gssapi-keyex,gssapi-with-mic,hostbased ?#注意:這里有hostbased身份驗證方式 debug1: Next authentication method: hostbased debug1: Remote: Accepted by .shosts. ? ?#注意:這里加載服務端的.shosts文件 debug1: Remote: Accepted host ssh-client ip 192.168.27.143 client_user root server_user root debug1: Authentication succeeded (hostbased). #注意:這里表示hostbased身份驗證方式成功 debug1: channel 0: new [client-session] debug1: Requesting no-more-sessions@openssh.com debug1: Entering interactive session. debug1: Sending environment. debug1: Sending env LANG = en_US.UTF-8 Last login: Mon Jun 13 20:51:06 2011 from ssh-client 注意:通過hostbased方式驗證要保證登錄的客戶端的用戶UID與服務端的UID一致. 最后我們建議關閉hostbased和rhostsrsa驗證方式,如下: HostbasedAuthentication no IgnoreUserKnownHosts yes IgnoreRhosts yes 16)SSH的協議v1/v2 我們現在一般都使用SSH-v2,只有在比較老的系統上會看到僅支持ssh-v1,或一些網絡設備. 我們可以調整SSH服務,支持ssh-v1,如下: Protocol 1 同時下面兩個選項是只在ssh-v1下有用,如下: RSAAuthentication RhostsRSAAuthentication 最后建議僅使用ssh-v2,同時關閉RSAAuthentication/RhostsRSAAuthentication,如下: Protocol 2 RhostsRSAAuthentication no RSAAuthentication no 17)認證時限,未認證連接與認證次數 我們可以通過MaxStartups選項對未認證連接的個數進行調整. 下面的連接就是一個未認證連接: telnet 192.168.27.142 22 Trying 192.168.27.142... Connected to 192.168.27.142. Escape character is '^]'. SSH-2.0-OpenSSH_5.3 同樣一個ssh的登錄,在沒有成功驗證前,也是一個未認證連接,如下: ssh ?root@192.168.27.142 ? ? ? ? ? ? ? ? ? ? ? ? ? ? root@192.168.27.142's password: MaxStartups 10表示可以有10個ssh的半連接狀態,就像上面一樣. 這個選項一定要配合LoginGraceTime選項一起使用. LoginGraceTime表示認證的時限,我們可以調整認證的時間限制,例如: LoginGraceTime 20 即在20秒之內不能完成認證,則斷開,如下: ssh ?root@192.168.27.142 root@192.168.27.142's password:? Connection closed by 192.168.27.142 注意在這里如果密碼輸入錯誤,則重新計時,如果我們輸錯了密碼,計時將重新開始,幸運的是我們有MaxAuthTries,來解決認證次數的問題. MaxAuthTries 1 這里表示只允許輸錯一回密碼. 我們要注意的是除了SSH自身的選項控制認證次數外,它還通過pam進行驗證,所以如果我們設置MaxAuthTries 10,則允許輸錯密碼的次數可能還是3,如果MaxAuthTries 2,則以MaxAuthTries為準. 如果是MaxAuthTries 2,我們輸錯密碼的提示如下: ssh ?root@192.168.27.142 root@192.168.27.142's password:? Permission denied, please try again. root@192.168.27.142's password:? Received disconnect from 192.168.27.142: 2: Too many authentication failures for root 18)DNS反向解析 UseDNS選項來決定是否對遠程主機名進行反向解析,以檢查此主機名是否與其IP地址真實對應.默認值為"yes". 用strace對sshd登錄服務時進行系統調用跟蹤,我們發現如果采用UseDNS yes,客戶端登錄時,SSH服務端將會打開/etc/hosts,找對映的ip/hostname的解析記錄, 如果沒有找到,這時將會用利用/lib/libnss_dns.so.2動態鏈接庫去/etc/resolv.conf中找DNS服務器做反向解析查詢. 下面是/etc/hosts沒有客戶端的ip/hostname解析記錄的strace調用過程,如下: 2793 ?open("/etc/resolv.conf", O_RDONLY) = 4 ? ? ? ? ? ? ? /*打開/etc/resolv.conf*/ 2793 ?fstat64(4, {st_mode=S_IFREG|0644, st_size=92, ...}) = 0 2793 ?mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb76f1000 2793 ?read(4, "# Generated by NetworkManager\ndo"..., 4096) = 92 2793 ?read(4, "", 4096) ? ? ? ? ? ? ? ? = 0 2793 ?close(4) ? ? ? ? ? ? ? ? ? ? ? ? ?= 0 2793 ?munmap(0xb76f1000, 4096) ? ? ? ? ?= 0 2793 ?open("/etc/host.conf", O_RDONLY) ?= 4 ? ? ? ? ? ? ? ?/*打開/etc/host.conf,這步確認解析的順序,是hosts(/etc/hosts)還是bind(/etc /resolv.conf)*/ 2793 ?fstat64(4, {st_mode=S_IFREG|0644, st_size=26, ...}) = 0 2793 ?mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb76f1000 2793 ?read(4, "multi on\norder hosts,bind\n", 4096) = 26 2793 ?read(4, "", 4096) ? ? ? ? ? ? ? ? = 0 2793 ?close(4) ? ? ? ? ? ? ? ? ? ? ? ? ?= 0 2793 ?munmap(0xb76f1000, 4096) ? ? ? ? ?= 0 2793 ?futex(0xffab44, FUTEX_WAKE_PRIVATE, 2147483647) = 0 2793 ?open("/etc/hosts", O_RDONLY|O_CLOEXEC) = 4 ? ? ? ? ? /*打開/etc/hosts*/ 2793 ?fstat64(4, {st_mode=S_IFREG|0644, st_size=187, ...}) = 0 2793 ?mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb76f1000 2793 ?read(4, "#127.0.0.1\tlocalhost.localdomain"..., 4096) = 187 2793 ?read(4, "", 4096) ? ? ? ? ? ? ? ? = 0 2793 ?close(4) ? ? ? ? ? ? ? ? ? ? ? ? ?= 0 2793 ?munmap(0xb76f1000, 4096) ? ? ? ? ?= 0 2793 ?open("/etc/ld.so.cache", O_RDONLY) = 4 2793 ?fstat64(4, {st_mode=S_IFREG|0644, st_size=81400, ...}) = 0 2793 ?mmap2(NULL, 81400, PROT_READ, MAP_PRIVATE, 4, 0) = 0xb7593000 2793 ?close(4) ? ? ? ? ? ? ? ? ? ? ? ? ?= 0 2793 ?open("/lib/libnss_dns.so.2", O_RDONLY) = 4 ? ? ? ? ? /*打開libnss_dns.so.2動態鏈接庫*/ 2793 ?read(4, "\177ELF\1\1\1\3\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\0\f\0\0004\0\0\0"..., 512) = 512 2793 ?fstat64(4, {st_mode=S_IFREG|0755, st_size=25596, ...}) = 0 2793 ?mmap2(NULL, 24704, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 4, 0) = 0x71a000 2793 ?mmap2(0x71f000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 4, 0x4) = 0x71f000 2793 ?close(4) ? ? ? ? ? ? ? ? ? ? ? ? ?= 0 2793 ?mprotect(0x71f000, 4096, PROT_READ) = 0 2793 ?munmap(0xb7593000, 81400) ? ? ? ? = 0 2793 ?socket(PF_INET, SOCK_DGRAM|SOCK_NONBLOCK, IPPROTO_IP) = 4 ? ? ? ?/*連接DNS(192.168.27.2)*/ 2793 ?connect(4, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("192.168.27.2")}, 16) = 0 2793 ?gettimeofday({1308208753, 877706}, NULL) = 0 2793 ?poll([{fd=4, events=POLLOUT}], 1, 0) = 1 ([{fd=4, revents=POLLOUT}]) 2793 ?send(4, "G\323\1\0\0\1\0\0\0\0\0\0\003143\00227\003168\003192\7in-a"..., 45, MSG_NOSIGNAL) = 45 2793 ?poll([{fd=4, events=POLLIN}], 1, 5000) = 1 ([{fd=4, revents=POLLIN}]) 2793 ?ioctl(4, FIONREAD, [122]) ? ? ? ? = 0 2793 ?recvfrom(4, "G\323\201\203\0\1\0\0\0\1\0\0\003143\00227\003168\003192\7in-a"..., 1024, 0, {sa_family=AF_INET, sin_port=htons(5 3), sin_addr=inet_addr("192.168.27.2")}, [16]) = 122 ? ? ? ? ? ? ? ? ? /*返回解析記錄*/ 2793 ?close(4) ? ? ? ? ? ? ? ? ? ? ? ? ?= 0 注意: 這是根據/etc/host.conf中配置的解析順序(hosts/bind)來的,如果/etc/hosts中有解析記錄,則不會通過/etc/resolv.conf中的DNS進行反向解析. 如果我們關閉反向解析查詢,即UseDNS = no,此時則不會用/etc/host.conf等文件進行hosts/bind反向解析查詢. 我們建議使用UseDNS no,因為這樣效率更高. 19)macs消息摘要算法 指定允許在SSH-2中使用哪些消息摘要算法來進行數據校驗. 可以使用逗號分隔的列表來指定允許使用多個算法.默認值(包含所有可以使用的算法)是: hmac-md5,hmac-sha1,umac-64@openssh.com,hmac-ripemd160,hmac-ripemd160@openssh.com,hmac-sha1-96,hmac-md5-96 Hash信息驗證碼HMAC(Hash message authentication codes)驗證接收消息和發送消息的完全一致性(完整性).這在數據交換中非常關鍵,尤其當傳輸媒介如公共網絡中不提供安全保證時更顯其重要性. HMAC結合hash算法和共享密鑰提供完整性.Hash散列通常也被當成是數字簽名,但這種說法不夠準確,兩者的區別在于:Hash散列使用共享密鑰,而數字簽名基于公鑰技術. hash算法也稱為消息摘要 1)雙方必須在通信的兩個原頭處各自執行Hash函數計算. 2)使用Hash函數很容易從消息計算出消息摘要,但其逆向反演過程以目前計算機的運算能力幾乎不可實現. 例如: 發送方首先使用HMAC算法和共享密鑰計算消息檢查和,然后將計算結果A封裝進數據包中一起發送;接收方再對所接收的消息執行HMAC計算得出結果B,并將B與A進行比較.如果消息在傳輸中遭篡改致使B與A不一致,接收方丟棄該數據包. 有兩種最常用的hash函數: ·HMAC-MD5 MD5(消息摘要5)基于RFC1321.MD5對MD4做了改進,計算速度比MD4稍慢,但安全性能得到了進一步改善.MD5在計算中使用了64個32位常數,最終生成一個128位的完整性檢查和.? ·HMAC-SHA 安全Hash算法定義在NIST FIPS 180-1,其算法以MD5為原型.SHA在計算中使用了79個32位常數,最終產生一個160位完整性檢查和.SHA檢查和長度比MD5更長,因此安全性也更高. 說到底MACs就是用于確保雙方數據傳輸的完整性. SSH服務端提供可以使用的消息摘要算法,由客戶端指定要使用哪種消息摘要. SSH服務端默認配置支持所有消息摘要算法,我們用客戶端連接服務端,可以看有支持的所有消息摘要算法,如下: ssh -vv 192.168.27.142? OpenSSH_5.3p1, OpenSSL 1.0.0-fips 29 Mar 2010 debug1: Reading configuration data /etc/ssh/ssh_config debug1: Applying options for * debug2: ssh_connect: needpriv 0 debug1: Connecting to 192.168.27.142 [192.168.27.142] port 22. debug1: Connection established. debug1: read PEM private key done: type DSA debug1: read PEM private key done: type RSA debug1: permanently_set_uid: 0/0 debug1: identity file /root/.ssh/identity type -1 debug2: key_type_from_name: unknown key type '-----BEGIN' debug2: key_type_from_name: unknown key type 'Proc-Type:' debug2: key_type_from_name: unknown key type 'DEK-Info:' debug2: key_type_from_name: unknown key type '-----END' debug1: identity file /root/.ssh/id_rsa type 1 debug1: identity file /root/.ssh/id_dsa type -1 debug1: Remote protocol version 2.0, remote software version OpenSSH_5.3 debug1: match: OpenSSH_5.3 pat OpenSSH* debug1: Enabling compatibility mode for protocol 2.0 debug1: Local version string SSH-2.0-OpenSSH_5.3 debug2: fd 3 setting O_NONBLOCK debug1: SSH2_MSG_KEXINIT sent debug1: SSH2_MSG_KEXINIT received debug2: kex_parse_kexinit: diffie-hellman-group-exchange-sha256,diffie-hellman-group-exchange-sha1,diffie-hellman-group14-sha1,diffie-hellman-group1-sha1 debug2: kex_parse_kexinit: ssh-rsa,ssh-dss debug2: kex_parse_kexinit: aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,aes256-cbc,arcfour,rijndael-cbc@lysator.liu.se debug2: kex_parse_kexinit: aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,aes256-cbc,arcfour,rijndael-cbc@lysator.liu.se debug2: kex_parse_kexinit: hmac-md5,hmac-sha1,umac-64@openssh.com,hmac-ripemd160,hmac-ripemd160@openssh.com,hmac-sha1-96,hmac-md5-96 debug2: kex_parse_kexinit: hmac-md5,hmac-sha1,umac-64@openssh.com,hmac-ripemd160,hmac-ripemd160@openssh.com,hmac-sha1-96,hmac-md5-96 /*這里就是服務端與客戶端的消息摘要算法的確定*/ 我們修改ssh服務端的摘要算法如下: vi /etc/ssh/sshd_config macs hmac-md5,hmac-sha1 我們修改ssh客戶端的摘要算法如下: vi /etc/ssh/ssh_config macs hmac-sha1 我們再次登錄ssh服務端,如下: [root@ssh-client ~]# ssh -vv 192.168.27.142? OpenSSH_5.3p1, OpenSSL 1.0.0-fips 29 Mar 2010 debug1: Reading configuration data /etc/ssh/ssh_config debug1: Applying options for * debug2: mac_setup: found hmac-sha1 debug2: ssh_connect: needpriv 0 debug1: Connecting to 192.168.27.142 [192.168.27.142] port 22. debug1: Connection established. debug1: read PEM private key done: type DSA debug1: read PEM private key done: type RSA debug1: permanently_set_uid: 0/0 debug1: identity file /root/.ssh/identity type -1 debug2: key_type_from_name: unknown key type '-----BEGIN' debug2: key_type_from_name: unknown key type 'Proc-Type:' debug2: key_type_from_name: unknown key type 'DEK-Info:' debug2: key_type_from_name: unknown key type '-----END' debug1: identity file /root/.ssh/id_rsa type 1 debug1: identity file /root/.ssh/id_dsa type -1 debug1: Remote protocol version 2.0, remote software version OpenSSH_5.3 debug1: match: OpenSSH_5.3 pat OpenSSH* debug1: Enabling compatibility mode for protocol 2.0 debug1: Local version string SSH-2.0-OpenSSH_5.3 debug2: fd 3 setting O_NONBLOCK debug1: SSH2_MSG_KEXINIT sent debug1: SSH2_MSG_KEXINIT received debug2: kex_parse_kexinit: diffie-hellman-group-exchange-sha256,diffie-hellman-group-exchange-sha1,diffie-hellman-group14-sha1,diffie-hellman-group1-sha1 debug2: kex_parse_kexinit: ssh-rsa,ssh-dss debug2: kex_parse_kexinit: aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,aes256-cbc,arcfour,rijndael-cbc@lysator.liu.se debug2: kex_parse_kexinit: aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,aes256-cbc,arcfour,rijndael-cbc@lysator.liu.se debug2: kex_parse_kexinit: hmac-sha1 debug2: kex_parse_kexinit: hmac-sha1 注:這里選擇用hmac-sha1摘要算法. 最后我們建議使用hmac-md5 20)authorized_keys的權限檢查 StrictModes指定是否要求在接受連接請求前對用戶主目錄和相關的配置文件進行宿主和權限檢查. 我們首先采用公/私鑰的方式進行驗證,同時打開strictmodes選項. 如下: vi /etc/ssh/sshd_config strictmodes yes 此時SSH服務端的authorized_keys文件的權限是400,如下: ls -l /root/.ssh/authorized_keys? -r-------- 1 root root 605 Jun 17 09:02 /root/.ssh/authorized_keys 我們將SSH服務端的authorized_keys文件的權限改為777,如下: chmod 777 /root/.ssh/authorized_keys 此時不能再通過公/私鑰的方式進行驗證了,如下: ssh -v root@192.168.27.142 OpenSSH_5.3p1, OpenSSL 1.0.0-fips 29 Mar 2010 debug1: Reading configuration data /etc/ssh/ssh_config debug1: Applying options for * debug1: Connecting to 192.168.27.142 [192.168.27.142] port 22. debug1: Connection established. debug1: read PEM private key done: type DSA debug1: read PEM private key done: type RSA debug1: permanently_set_uid: 0/0 debug1: identity file /root/.ssh/identity type -1 debug1: identity file /root/.ssh/id_rsa type 1 debug1: identity file /root/.ssh/id_dsa type 2 debug1: Remote protocol version 2.0, remote software version OpenSSH_5.3 debug1: match: OpenSSH_5.3 pat OpenSSH* debug1: Enabling compatibility mode for protocol 2.0 debug1: Local version string SSH-2.0-OpenSSH_5.3 debug1: SSH2_MSG_KEXINIT sent debug1: SSH2_MSG_KEXINIT received debug1: kex: server->client aes128-ctr hmac-sha1 none debug1: kex: client->server aes128-ctr hmac-sha1 none debug1: SSH2_MSG_KEX_DH_GEX_REQUEST(1024<2048<8192) sent debug1: expecting SSH2_MSG_KEX_DH_GEX_GROUP debug1: SSH2_MSG_KEX_DH_GEX_INIT sent debug1: expecting SSH2_MSG_KEX_DH_GEX_REPLY debug1: Host '192.168.27.142' is known and matches the RSA host key. debug1: Found key in /root/.ssh/known_hosts:1 debug1: ssh_rsa_verify: signature correct debug1: SSH2_MSG_NEWKEYS sent debug1: expecting SSH2_MSG_NEWKEYS debug1: SSH2_MSG_NEWKEYS received debug1: SSH2_MSG_SERVICE_REQUEST sent debug1: SSH2_MSG_SERVICE_ACCEPT received debug1: Authentications that can continue: publickey,gssapi-keyex,gssapi-with-mic,password,hostbased debug1: Next authentication method: publickey /*采用publickey的方式進行身份驗證,但是因為authorized_keys文件的權限是777,所以驗證不能通過*/ debug1: Trying private key: /root/.ssh/identity debug1: Offering public key: /root/.ssh/id_rsa debug1: Authentications that can continue: publickey,gssapi-keyex,gssapi-with-mic,password,hostbased debug1: Offering public key: /root/.ssh/id_dsa debug1: Authentications that can continue: publickey,gssapi-keyex,gssapi-with-mic,password,hostbased debug1: Next authentication method: password ?/*此時只能采用password進行身份驗證*/ root@192.168.27.142's password:? 最后我們強烈建議使用默認值"yes"來預防可能出現的低級錯誤. 21)阻止root(uid=0)用戶使用ssh遠程登錄 將PermitRootLogin選項改為no,即可阻止root用戶遠程登錄. 默認是:PermitRootLogin yes 如果調整為: PermitRootLogin without-password 則可以用root用戶訪問ssh服務端,但前提是使用公/私鑰的方式訪問,而不能是password的認證方式. 建議采用: PermitRootLogin no 22)不允許root(uid=0)空口令登錄系統 將PermitEmptyPasswords選項改為no,即可阻止root用戶以空口令的方式登錄.默認為no. 如改成PermitEmptyPasswords yes,可允許root用戶以空口令的方式登錄系統. 建議采用: PermitEmptyPasswords no 23)挑戰應答驗證 將ChallengeResponseAuthentication改為no則關閉挑戰應答驗證. 建議將挑戰應答驗證方式關閉,如下: ChallengeResponseAuthentication no 24)分離特權 將UsePrivilegeSeparation改為yes即客戶端連接ssh服務端時,SSH服務端通過創建非特權子進程處理接入請求的方法來進行權限分離,默認值是"yes". 這樣做的目的是為了防止通過有缺陷的子進程提升權限,從而使系統更加安全。 將ssh服務端改成如下的配置: vi /etc/ssh/sshd_config UsePrivilegeSeparation no ps -ef|grep ssh avahi ? ? 1113 ? ? 1 ?0 10:11 ? ? ? ? ?00:00:00 avahi-daemon: registering [ssh-server.local] root ? ? ?1682 ? ? 1 ?0 10:13 ? ? ? ? ?00:00:00 sshd: root@pts/0? root ? ? ?2046 ? ? 1 ?0 11:13 ? ? ? ? ?00:00:00 /usr/sbin/sshd 客戶端連接服務端,不進行認證,如下: ssh 192.168.27.142 ? ? root@192.168.27.142's password:? 查看服務端ssh進程連接狀態,如下: ps -ef|grep ssh avahi ? ? 1113 ? ? 1 ?0 10:11 ? ? ? ? ?00:00:00 avahi-daemon: registering [ssh-server.local] root ? ? ?1682 ? ? 1 ?0 10:13 ? ? ? ? ?00:00:00 sshd: root@pts/0? root ? ? ?2046 ? ? 1 ?0 11:13 ? ? ? ? ?00:00:00 /usr/sbin/sshd root ? ? ?2097 ?2046 ?0 11:30 ? ? ? ? ?00:00:00 sshd: root ? ? ?? 注: 我們看到的sshd連接如下,sshd: root. 修改服務端的UsePrivilegeSeparation為yes vi /etc/ssh/sshd_config UsePrivilegeSeparation yes 客戶端連接服務端,不進行認證,如下: ssh 192.168.27.142 ? ? root@192.168.27.142's password:? 查看服務端ssh進程連接狀態,如下: ps -ef|grep ssh ? ? ? ?? avahi ? ? 1113 ? ? 1 ?0 10:11 ? ? ? ? ?00:00:00 avahi-daemon: registering [ssh-server.local] root ? ? ?1682 ? ? 1 ?0 10:13 ? ? ? ? ?00:00:00 sshd: root@pts/0? root ? ? ?2119 ? ? 1 ?0 11:32 ? ? ? ? ?00:00:00 /usr/sbin/sshd root ? ? ?2121 ?2119 ?0 11:32 ? ? ? ? ?00:00:00 sshd: root [priv] sshd ? ? ?2122 ?2121 ?0 11:32 ? ? ? ? ?00:00:00 sshd: root [net]? 注: 我們看到ssh在認證時,分離出sshd: root [priv]和sshd: root [net] 我們用sshd的debug 3的方式看到,ssh服務當時的處理操作,如下: debug2: Network child is on pid 1988 ? ? ? ? ? ? ? ? ? ? ? ? ?? debug3: preauth child monitor started ? ? ? ? ? ? ? ? ? ? ? ? ? debug3: mm_request_receive entering ? ? ? ? ? ? ? ? ? ? ? ? ? ? debug3: privsep user:group 74:74 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? debug1: permanently_set_uid: 74/74 ? ? ? 注意:在登錄過程中,ssh派生子進程時會用setuid到sshd用戶. 25)使用PAM 在SSH服務端使用UsePAM yes,則ssh服務端會加載/etc/pam.d/sshd,我們做下面的試驗 修改sshd的pam,加入session ? ? required ? ? ?pam_limits.so,如下: vi /etc/pam.d/sshd session ? ? required ? ? ?pam_limits.so 修改cat /etc/security/limits.conf ,如下: * ? ? ? ? ? ? ? soft ? ?core ? ? ? ? ? ?1000 客戶端登錄SSH服務端,查看core limit,如下: ulimit -c 1000 關閉SSH服務端的的PAM認證,如下: vi /etc/ssh/sshd_config UsePAM no 再次從客戶端登錄ssh服務端,查看core limit,如下: ulimit -c 0 我們證明ssh/PAM是起作用的,通過SSH/PAM可實現limit.conf的動態加載. 我們建議使用SSH/PAM,如下: UsePAM yes 26)開啟壓縮選項 我們可以打開Compression選項,即: vi /etc/ssh/sshd_config Compression yes 測試的壓縮效果如下: scp ?-v /tmp/test root@192.168.27.142:/tmp ?? 略 debug1: Sending command: scp -v -t /tmp Sending file modes: C0644 209715200 test Sink: C0644 209715200 test test ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?100% ?200MB ? 9.1MB/s ? 00:22 ? ? debug1: client_input_channel_req: channel 0 rtype exit-status reply 0 debug1: channel 0: free: client-session, nchannels 1 debug1: fd 0 clearing O_NONBLOCK debug1: fd 1 clearing O_NONBLOCK Transferred: sent 209936128, received 56592 bytes, in 22.3 seconds Bytes per second: sent 9430610.8, received 2542.2 debug1: Exit status 0 注: 用SCP時不啟用壓縮選項,此時傳輸200MB的數據大概用了22秒. scp啟用壓縮選項,即在命令行中加入-C,如下: scp ?-C -v /tmp/test root@192.168.27.142:/tmp Executing: program /usr/bin/ssh host 192.168.27.142, user root, command scp -v -t /tmp Sending file modes: C0644 209715200 test test ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?0% ? ?0 ? ? 0.0KB/s ? --:-- ETASink: C0644 209715200 test test ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?100% ?200MB ?14.3MB/s ? 00:14 ? ? debug1: client_input_channel_req: channel 0 rtype exit-status reply 0 debug1: channel 0: free: client-session, nchannels 1 debug1: fd 0 clearing O_NONBLOCK debug1: fd 1 clearing O_NONBLOCK Transferred: sent 615920, received 54144 bytes, in 13.6 seconds Bytes per second: sent 45267.3, received 3979.3 debug1: Exit status 0 debug1: compress outgoing: raw data 209830605, compressed 448191, factor 0.00 debug1: compress incoming: raw data 29449, compressed 14259, factor 0.48 注: 我們看到啟用壓縮選項,此時傳輸200MB的數據只用了14秒. 最后它還顯示了壓縮的詳細信息. 27)SSH監聽端口 我們可以指定ssh監聽的端口,使用Port選項,也可以多次使用Port,來指定多個端口,我們試一下: vi /etc/ssh/sshd_config Port 22 Port 56000 重啟SSH服務: /etc/init.d/sshd restart 查看端口: netstat -tulnp|grep ssh? tcp ? ? ? ?0 ? ? ?0 0.0.0.0:56000 ? ? ? ? ? ? ? 0.0.0.0:* ? ? ? ? ? ? ? ? ? LISTEN ? ? ?1810/sshd ? ? ? ? ?? tcp ? ? ? ?0 ? ? ?0 0.0.0.0:22 ? ? ? ? ? ? ? ? ?0.0.0.0:* ? ? ? ? ? ? ? ? ? LISTEN ? ? ?1810/sshd ? ? ? 注:我們看到已經指定了22和56000兩個端口. 我們建議使用一個1024端口以上的SSH綁定端口,如54321等 28)SSH的網絡接口 我們可以指定要綁定的網絡接口,使用的是ListenAddress,默認是監聽所有接口,我們給它綁定到eth1(192.168.27.142),如下: vi /etc/ssh/sshd_config ListenAddress 192.168.27.142 重啟SSH服務: /etc/init.d/sshd restart 查看綁定地址: tcp ? ? ? ?0 ? ? ?0 192.168.27.142:56000 ? ? ? ?0.0.0.0:* ? ? ? ? ? ? ? ? ? LISTEN ? ? ?1838/sshd ? ? ? ? ?? tcp ? ? ? ?0 ? ? ?0 192.168.27.142:22 ? ? ? ? ? 0.0.0.0:* ? ? ? ? ? ? ? ? ? LISTEN ? ? ?1838/sshd ? ? ? ? ?? 我們建議綁定到內網通訊的網卡地址,如192.168.27.142,而不是公網地址. 29)SSH的協議族: 我們可以指定SSH的協議族,使用的是AddressFamily,默認是使用所有協議族any,我們還可以指定inet(ipv4),inet6(ipv6). 這里建議使用any,支持所有的協議族. 30)外部子系統 我們可以配置一個外部的子系統,僅用于SSH-V2協議,一般這里使用sftp,如下: Subsystem ? ? ? sftp ? ?/usr/libexec/openssh/sftp-server 如關閉該選項,將無法使用sftp. 我們看一下使用sftp的通訊過程,如下: sftp -v 192.168.27.142 ? ? ? ?/*采用sftp的方式連接ssh服務端*/ Connecting to 192.168.27.142... OpenSSH_5.3p1, OpenSSL 1.0.0-fips 29 Mar 2010 debug1: Reading configuration data /etc/ssh/ssh_config debug1: Applying options for * debug1: Connecting to 192.168.27.142 [192.168.27.142] port 22. debug1: Connection established. debug1: permanently_set_uid: 0/0 debug1: identity file /root/.ssh/id_rsa type 1 debug1: identity file /root/.ssh/id_dsa type 2 debug1: Remote protocol version 2.0, remote software version OpenSSH_5.3 debug1: match: OpenSSH_5.3 pat OpenSSH* debug1: Enabling compatibility mode for protocol 2.0 debug1: Local version string SSH-2.0-OpenSSH_5.3 debug1: SSH2_MSG_KEXINIT sent debug1: SSH2_MSG_KEXINIT received debug1: kex: server->client aes128-ctr hmac-md5 none debug1: kex: client->server aes128-ctr hmac-md5 none debug1: SSH2_MSG_KEX_DH_GEX_REQUEST(1024<1024<8192) sent debug1: expecting SSH2_MSG_KEX_DH_GEX_GROUP debug1: SSH2_MSG_KEX_DH_GEX_INIT sent debug1: expecting SSH2_MSG_KEX_DH_GEX_REPLY debug1: Host '192.168.27.142' is known and matches the RSA host key. debug1: Found key in /root/.ssh/known_hosts:1 debug1: ssh_rsa_verify: signature correct debug1: SSH2_MSG_NEWKEYS sent debug1: expecting SSH2_MSG_NEWKEYS debug1: SSH2_MSG_NEWKEYS received debug1: SSH2_MSG_SERVICE_REQUEST sent debug1: SSH2_MSG_SERVICE_ACCEPT received debug1: Authentications that can continue: gssapi-keyex,gssapi-with-mic,password,hostbased debug1: Next authentication method: password root@192.168.27.142's password:? debug1: Authentication succeeded (password). debug1: channel 0: new [client-session] debug1: Requesting no-more-sessions@openssh.com debug1: Entering interactive session. debug1: Sending environment. debug1: Sending env LANG = en_US.UTF-8 debug1: Sending subsystem: sftp ? ? ? ? /*在這里啟用了sftp子系統*/ sftp>? 我們看一下服務端的進程: ps -ef|grep ssh avahi ? ? 1133 ? ? 1 ?0 03:08 ? ? ? ? ?00:00:00 avahi-daemon: registering [ssh-server.local] root ? ? ?1718 ? ? 1 ?0 03:14 ? ? ? ? ?00:00:00 sshd: root@pts/0? root ? ? ?2005 ? ? 1 ?0 03:50 ? ? ? ? ?00:00:00 /usr/sbin/sshd root ? ? ?2023 ?2005 ?0 03:52 ? ? ? ? ?00:00:00 sshd: root@notty? root ? ? ?2025 ?2023 ?0 03:52 ? ? ? ? ?00:00:00 /usr/libexec/openssh/sftp-server 注: 我們看到服務端啟用了sftp-server為sftp客戶請求服務. 31)設定主機的私鑰文件 在ssh中可以用HostKey指定主機的私鑰文件,如不指定則無法啟用ssh服務,默認的是如下的配置: HostKey /etc/ssh/ssh_host_rsa_key HostKey /etc/ssh/ssh_host_dsa_key 我們看到這里支持兩個非對稱加密算法,分別是rsa和dsa. 事實上在進入身份驗證之前,客戶端要與服務端確認服務端的公/私鑰是否改變過, 即客戶端會用服務端主機公鑰對一段消息進行加密,而服務端會用自己的主機密鑰進行解密. 從而校驗數據,達到主機身份確認的效果. 如果主機被重裝過,或重新生成了新的RSA/DSA密鑰,則登錄該主機時會重新在客戶端生成公鑰并寫入到~/.ssh/known_hosts 32)Kerberos的身份驗證 Kerberos是針對分布式環境而設計的,如果不需要可以關閉這種身份驗證方式. 所以建議如下的配置: kerberosauthentication no kerberosorlocalpasswd no kerberosticketcleanup yes 三)SSH客戶端的配置項: 1)客戶端發現SSH服務端timeout后,可以在指定的秒數后斷開連接,避免不必要的等待,這個參數就是: ConnectTimeout 3 注:這里是等待3秒. 例如:我們連接一個不存在的服務器(192.168.27.155) time ssh -v 192.168.27.155 OpenSSH_5.3p1, OpenSSL 1.0.0-fips 29 Mar 2010 debug1: Reading configuration data /etc/ssh/ssh_config debug1: Applying options for * debug1: Connecting to 192.168.27.155 [192.168.27.155] port 22. debug1: Allocated local port 1023. debug1: connect to address 192.168.27.155 port 22: Connection timed out ssh: connect to host 192.168.27.155 port 22: Connection timed out real ? ?0m3.029s user ? ?0m0.006s sys ? ? 0m0.007s 注:我們在這里看到一共等待在大概3秒鐘. 2)有關于客戶端的SSH壓縮設定,在客戶端如果設定Compression yes,則表示支持壓縮,壓縮會提高網絡吐吞量,但會增加CPU的消耗. 如果客戶大量使用gzip對數據壓縮后再通過scp傳輸,則ssh的compression并不會有任何效果,反而會降紙網絡吐吞量. 同時SSH V2中也不支持壓縮級別. 我們使用ssh的debug模式連接ssh服務端,可以看到壓縮的情況,我們在斷開時看到如下的信息: [test@ssh-server ~]$ exitdebug1: client_input_channel_req: channel 0 rtype exit-status reply 0 debug1: client_input_channel_req: channel 0 rtype eow@openssh.com reply 0 logout debug1: channel 0: free: client-session, nchannels 1 Connection to 192.168.27.142 closed. Transferred: sent 1104, received 2576 bytes, in 4.9 seconds Bytes per second: sent 225.7, received 526.7 debug1: Exit status 0 debug1: compress outgoing: raw data 459, compressed 299, factor 0.65 debug1: compress incoming: raw data 455, compressed 310, factor 0.68 3)我們也可以調整使用身份驗證方式的優先順序,我們用到的選項是PreferredAuthentications,如果我們優先使用password,那么可以設定如下的配置: PreferredAuthentications password,publickey,keyboard-interactive 4)我們可以設定CheckHostIP選項防止DNS欺騙,如下: 首先設定CheckHostIP選項,如下: vi /etc/ssh/ssh_config CheckHostIP yes 編輯hosts,設定192.168.27.142對映的主機名為ssh-server vi /etc/hosts 192.168.27.142 ?ssh-server ? ? ?# Added by NetworkManager 連接ssh服務端(ssh-server),注意這里用主機名連接,如下: ssh ? root@ssh-server ? root@ssh-server's password: 注:我們看到沒有問題. 我們這時修改/etc/hosts中ssh-server主機名對映的IP,如下: vi /etc/hosts 192.168.27.143 ?ssh-sever 再次連接ssh服務端(ssh-server),如下: ssh ? test@ssh-server ? ? @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ? 注:我們看到checkhostip起到了作用. @ ? ? ? WARNING: POSSIBLE DNS SPOOFING DETECTED! ? ? ? ? ?@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ The RSA host key for ssh-server has changed, and the key for the corresponding IP address 192.168.27.143 is unknown. This could either mean that DNS SPOOFING is happening or the IP address for the host and its host key have changed at the same time. @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ?注:這條信息不是checkhostip產生的. @ ? ?WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! ? ? @ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY! Someone could be eavesdropping on you right now (man-in-the-middle attack)! It is also possible that the RSA host key has just been changed. The fingerprint for the RSA key sent by the remote host is 49:35:e5:fe:1e:f4:cd:e2:50:d6:2e:57:35:cb:45:42. Please contact your system administrator. Add correct host key in /root/.ssh/known_hosts to get rid of this message. Offending key in /root/.ssh/known_hosts:1 Password authentication is disabled to avoid man-in-the-middle attacks. Keyboard-interactive authentication is disabled to avoid man-in-the-middle attacks. Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password,hostbased). 5)處理known_hosts的三種方式. 當用ssh連接對方的主機時,如果known_hosts中沒有對方主機的公鑰,則會看到一個加入主機公鑰確認身份的提示信息,如下: ssh ? test@ssh-server ? The authenticity of host 'ssh-server (192.168.27.142)' can't be established. RSA key fingerprint is ce:0c:74:71:87:a2:4a:92:98:55:25:f4:51:62:ea:59. Are you sure you want to continue connecting (yes/no)?? 這是因為客戶端配置了StrictHostKeyChecking ask造成的. 我們可以調整StrictHostKeyChecking選項為no,這樣會把對方的公鑰直接加入到known_hosts文件中. 如果調整StrictHostKeyChecking選項為yes,這樣直接拒絕加入對方的公鑰,需要手工來填加.如下: ssh ? test@ssh-server ? No RSA host key is known for ssh-server and you have requested strict checking. Host key verification failed. 6)有關于known_hosts的兩種文件格式 一種是主機名(IP)明文存放的格式 一種是主機名(IP)被哈希過的格式 我們可以通過HashKnownHosts這個選項來調整,如下: vi /etc/ssh/ssh_config HashKnownHosts yes 最后我們看一下明文存放的格式,如下: ssh-server ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAmgy1TPb2Beaw+XZa2ZY129nmE8klTMFPeJXZYbl577M/O2DLjInoYhK32mQKSc7NK3NQtxqkMp9Mz+vIdC4es Lz1+mRWjBOHPIfNjhLyl1RgZHKQRJZKamRiYru2sjjv5wPM21eSgaAozDF6pPAKgda0CQUcZSUokU7AZuBETlMJkEalp/+NIVdHuCrnoUmRcc4EW7v2/xAUb9pO12lgyhg2b j6S7BLSOSuEtKEjxHHrP5FOWwzTont78K1hrBHIFqgFmnyUIljWoRqzoufvSTMpDZHxlcjO+4o427QjS17viz7ftGpY6ObRzV1VHJJoCeUqdcWDJZDXMR+RlA1H9Q== 我們看到里面包括了主機名及非對稱加密的算法. 如果是哈希過的格式,如下: |1|u79t0dab3Mh8GnB7O4+zCzvw3Ho=|p4454t3nwTGWWWog5x21ouHANhc= ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAmgy1TPb2Beaw+XZa2ZY129nmE8klTMFPeJX ZYbl577M/O2DLjInoYhK32mQKSc7NK3NQtxqkMp9Mz+vIdC4esLz1+mRWjBOHPIfNjhLyl1RgZHKQRJZKamRiYru2sjjv5wPM21eSgaAozDF6pPAKgda0CQUcZSUokU7AZuB ETlMJkEalp/+NIVdHuCrnoUmRcc4EW7v2/xAUb9pO12lgyhg2bj6S7BLSOSuEtKEjxHHrP5FOWwzTont78K1hrBHIFqgFmnyUIljWoRqzoufvSTMpDZHxlcjO+4o427QjS17 viz7ftGpY6ObRzV1VHJJoCeUqdcWDJZDXMR+RlA1H9Q== 這里我們看不到主機名,因為它被哈希過了,但是還是可以看到使用的非對稱加密算法. 四)建議的配置 我們對整篇文章做了整理,建議用如下的配置,首先是SSH服務端的配置,如下: #################################### #僅使有Protocol 2 #綁定到56000端口 #綁定到內網IP #################################### Protocol 2 Port 56000 ListenAddress 192.168.27.141 #################################### #以下兩項配置僅用于Protocol 1 #################################### RhostsRSAAuthentication no RSAAuthentication no #################################### #關閉Kerberos身份驗證 #################################### kerberosauthentication no kerberosorlocalpasswd no kerberosticketcleanup yes #################################### #關閉挑戰/響應身份驗證(s/key) #################################### ChallengeResponseAuthentication no #################################### #關閉GSSAPI身份驗證 #################################### GSSAPIAuthentication no GSSAPICleanupCredentials yes #################################### #關閉公/私鑰身份驗證 #################################### PubkeyAuthentication no AuthorizedKeysFile ? ? ?.ssh/authorized_keys #################################### #關閉基于主機的身份驗證 #################################### HostbasedAuthentication no IgnoreUserKnownHosts yes IgnoreRhosts yes #################################### #開啟unix/password身份驗證 #################################### PasswordAuthentication yes #################################### #關閉X11轉發 #關閉除loopback外的其它網絡接口轉發 #關閉tcp端口轉發 #################################### X11Forwarding no GatewayPorts no AllowTcpForwarding no #################################### #日志級別調整為VERBOSE,默認為INFO #日志Facility為AUTH #################################### LogLevel VERBOSE SyslogFacility AUTH #################################### #關閉SSH客戶端與服務端的變量轉遞 #################################### AcceptEnv none #################################### #拒絕系統用戶通過SSH登錄 #################################### AllowUsers * DenyUsers daemon bin sys sync games man lp mail news uucp proxy www-data backup list irc gnats nobody Debian-exim statd identd sshd libuuid snmp #################################### #登錄警告信息 #登錄歡迎信息 #關閉SSH的補丁版本號 #關閉顯示最后一次登錄的信息 #################################### Banner /etc/issue PrintMotd yes ShowPatchLevel no PrintLastLog no #################################### #指定支持的數據對稱加密算法 #指定支持的消息摘要算法 #################################### ciphers aes128-cbc,aes192-cbc,aes256-cbc,aes128-ctr,aes192-ctr,aes256-ctr,3des-cbc,arcfour128,arcfour256,arcfour,blowfish-cbc,cast128-cbc macs hmac-md5,hmac-sha1,umac-64@openssh.com,hmac-ripemd160,hmac-ripemd160@openssh.com,hmac-sha1-96,hmac-md5-96 #################################### #每300秒向客戶端發送一次alive消息,判斷是否存活,如兩次均檢測失敗,則斷開與客戶端的連接 #關閉tcpkeepalive #################################### clientaliveinterval 300 clientalivecountmax 2 tcpkeepalive no #################################### #允許有1000次驗證連接請求,如20秒不能完成校驗,則斷開驗證連接請求 #有三次密碼驗證機會 #################################### MaxStartups 1000 LoginGraceTime 20 MaxAuthTries 3 #################################### #支持壓縮選項,從而提高數據通訊速度 #關閉DNS反向解析,從而提高驗證速度 #支持PAM,從而支持可插入的安全模塊,加載安全配置,如limit.conf等 #################################### Compression yes UseDNS no UsePAM yes #################################### #如其它用戶有讀取authorized.keys的權限,則拒絕連接 #拒絕root用戶登錄 #拒絕空口令的身份驗證 #用戶驗證時進程分離,ssh啟用setuid切換到sshd用戶啟動驗證進程 #拒絕在SSH驗證結束后使用/bin/login程序 #################################### strictmodes yes PermitRootLogin no PermitEmptyPasswords no UsePrivilegeSeparation yes UseLogin no #################################### #支持sftp子系統 #################################### Subsystem sftp /usr/lib/openssh/sftp-server #################################### #SSH的pid文件存放位置/var/run/ #################################### PidFile /var/run/sshd.pid #################################### #主機的私鑰存放位置 #################################### HostKey /etc/ssh/ssh_host_rsa_key HostKey /etc/ssh/ssh_host_dsa_key 下面是客戶端的配置,如下: ####################################### #針對所有主機的配置 ####################################### Host * ####################################### #支持所有協議族 #支持SSHv2/v1,優先使用SSHv2 #ssh連接目標主機的22端口 ####################################### AddressFamily any Protocol 2,1 Port 22 ####################################### #日志級別為VERBOSE #關閉批處理登錄方式 #防止DNS欺騙 #不檢查known_hosts中主機公鑰的正確性 #允許連接1024以下的端口 #允許三次嘗試密碼登錄 ####################################### LogLevel VERBOSE BatchMode no HashKnownHosts yes CheckHostIP yes StrictHostKeyChecking no NumberOfPasswordPrompts 3 ####################################### #僅使用hmac-md5做為消息摘要算法 #僅使用arcfour(rc4)做為數據加密算法 ####################################### MACs hmac-md5 Ciphers arcfour ####################################### #僅在protocol 1使用 ####################################### RhostsRSAAuthentication no RSAAuthentication no ####################################### #關閉挑戰響應身份驗證(s/key) ####################################### ChallengeResponseAuthentication no ####################################### #關閉基于主機的身份驗證 ####################################### HostbasedAuthentication no EnableSSHKeysign no NoHostAuthenticationForLocalhost no ####################################### #關閉GSSAPI身份驗證 ####################################### GSSAPIAuthentication no GSSAPIDelegateCredentials no GSSAPIKeyExchange no GSSAPITrustDNS no ####################################### #關閉公/私鑰身份驗證 ####################################### PubkeyAuthentication no ####################################### #開啟unix/password身份驗證 ####################################### PasswordAuthentication yes ####################################### #優先使用password身份驗證 ####################################### PreferredAuthentications password ####################################### #連接SSH服務端,發現timeout,3秒后強制斷開連接 #每300秒向SSH服務端發送1次alive消息 #如果兩次alive消息都沒有到達目的主機則斷開連接 #因為使用serveraliveinterval,所以關閉tcpkiipalive ####################################### ConnectTimeout 3 serveraliveinterval 300 serveralivecountmax 2 tcpkeepalive no ####################################### #關閉對X11的端口轉發 #關閉除loopback外的其它網絡接口轉發 #關閉轉發代理 #關閉ssh tunnel ####################################### ForwardX11 no ForwardX11Trusted no GatewayPorts no ForwardAgent no tunnel no ####################################### #開啟壓縮選項,級別為6 ####################################### Compression yes ####################################### #以下選項僅在protocol 1支持 ####################################### CompressionLevel 1 ConnectionAttempts 1
轉載于:https://www.cnblogs.com/xiaopengren/p/3467669.html
總結
- 上一篇: 初试牛刀---css中的小细节
- 下一篇: Combotree--别样的构建层级js