# SSH 遠端連線 - Book mode: https://hackmd.io/@ncnu-opensource/book [TOC] ## 為什麼需要遠端連線 ### 情境 - 在學校想用家裡的好電腦 - 想使用 server 但又不能直接進去機房 ### 為什麼要遠端連線 - 更好的運算能力 - 方便管理主機 - 透過遠端連線伺服器的服務 ## 遠端連線方式概覽 1. 文字介面明文傳輸: telnet, rsh (remote shell) 等為主,目前非常少用; 2. 文字介面加密傳輸: ssh 為主,已經取代上述的 telnet, rsh 等明碼方式; 3. 圖形介面: VNC, RDP 等較為常見 ### Telnet - 比較古老的系統環境會支援 - 使用明文來傳輸資料(未加密) - 可能會受到有心人士利用監聽軟體 (e.g tcpdump ) 的監聽竊取 - 例子: 遠端連線進主機時,需要輸入帳號密碼,若沒有加密,帳號密碼都會被別人看光光 - 還有哪些明文傳送? - rsh 一個命令列介面的電腦程式 - ftp 檔案傳輸伺服器 - http :::info #### DEMO: 可用 Wireshark / dsniff 看到明文傳輸 telnet 內容 - **Wireshark** - 開源的網路封包分析軟體 - 其他類似軟體:tcpdump - 另一支程式 **dsniff** 能自動幫我們找出明文的帳密 ::: ## SSH - 全名 : **S**ecure **Sh**ell 安全外殼協定 - 解決 telnet 不安全的問題 - 使用非對稱式加密方式做使用者驗證 :::info #### 不同加密方式[^REF_Crypt] 1. 對稱式加密 + 雙方都使用同一把密鑰加解密 ![](https://i.imgur.com/wM9nfL4.png) > 圖片來源 [基礎密碼學(對稱式與非對稱式加密技術). | by Chan @RiverChan | Medium](https://medium.com/@RiverChan/%E5%9F%BA%E7%A4%8E%E5%AF%86%E7%A2%BC%E5%AD%B8-%E5%B0%8D%E7%A8%B1%E5%BC%8F%E8%88%87%E9%9D%9E%E5%B0%8D%E7%A8%B1%E5%BC%8F%E5%8A%A0%E5%AF%86%E6%8A%80%E8%A1%93-de25fd5fa537) + 對稱式加密最大的弱點是,要是這把鑰匙在第一次傳送時,被中間人攔截且複製,再原封不動傳給接收方,那之後所有攔截到的加密訊息,都能被輕易破解 2. 非對稱式加密 (Asymmetric encryption) + 雙方各有一對公私鑰,互換公鑰後用對方的公鑰加密 ![](https://i.imgur.com/4rlNFQe.png) > 圖片來源 [基礎密碼學(對稱式與非對稱式加密技術). | by Chan @RiverChan | Medium](https://medium.com/@RiverChan/%E5%9F%BA%E7%A4%8E%E5%AF%86%E7%A2%BC%E5%AD%B8-%E5%B0%8D%E7%A8%B1%E5%BC%8F%E8%88%87%E9%9D%9E%E5%B0%8D%E7%A8%B1%E5%BC%8F%E5%8A%A0%E5%AF%86%E6%8A%80%E8%A1%93-de25fd5fa537) + 若單純用公私鑰,仍然會有被偽造的風險 + 數位簽章可解決 + 傳送方除了使用接收方的公鑰加密外,也使用自己的私鑰對該封加密訊息的 Hash 簽名,以達到二次驗證 ::: [^REF_Crypt]: [基礎密碼學(對稱式與非對稱式加密技術). 現代密碼學泛指透過數學演算法與電腦科學對資料(明文)進行加密和解密的科學。 | by Chan @RiverChan | Medium](https://medium.com/@RiverChan/%E5%9F%BA%E7%A4%8E%E5%AF%86%E7%A2%BC%E5%AD%B8-%E5%B0%8D%E7%A8%B1%E5%BC%8F%E8%88%87%E9%9D%9E%E5%B0%8D%E7%A8%B1%E5%BC%8F%E5%8A%A0%E5%AF%86%E6%8A%80%E8%A1%93-de25fd5fa537) :::info #### Hash 雜湊函式 $H(x) = x \mod B$ - 將不定長度訊息的輸入,演算成固定長度雜湊值的輸出[^hash] - 由雜湊值是無法反推出原來的訊息 - 雜湊值必須隨明文改變而改變 ::: [^hash]: [[資料結構] 雜湊 (Hash) - iT 邦幫忙::一起幫忙解決難題,拯救 IT 人的一天](https://ithelp.ithome.com.tw/articles/10208884) :::info #### 中間人攻擊 ![image alt](https://upload.wikimedia.org/wikipedia/commons/thumb/e/e7/Man_in_the_middle_attack.svg/800px-Man_in_the_middle_attack.svg.png?20110724142026 "title" =640x454) > 圖片來源 [File:Man in the middle attack.svg](https://commons.wikimedia.org/w/index.php?title=File:Man_in_the_middle_attack.svg&oldid=676928010). by [Miraceti](https://commons.wikimedia.org/wiki/User:Miraceti) . Wikimedia Commons > - 圖中 Mallory 是密碼學中常用來代表「惡意的攻擊者」虛構角色的人名[^Mallory] - **中間人攻擊** (**M**an-**i**n-**t**he-**M**iddle Attack, 縮寫: **MITM**) - 在密碼學和電腦安全領域中常提到的一個概念 - 指攻擊者與通訊的兩端分別建立獨立的聯絡,並交換其所收到的資料,使通訊的兩端認為他們正在通過一個私密的連接與對方直接對話,但事實上整個對談都被攻擊者完全控制。[^MITM] ::: [^Mallory]: [Alice and Bob - Wikipedia](https://en.wikipedia.org/wiki/Alice_and_Bob#Cryptographic_systems) [^MITM]: [中間人攻擊 - 維基百科,自由的百科全書](https://zh.wikipedia.org/wiki/%E4%B8%AD%E9%97%B4%E4%BA%BA%E6%94%BB%E5%87%BB) - SSH 的驗證方法[^REF_sshauth] 1. 基於密碼的安全驗證 - 知道帳號和密碼,就可以登入到遠端主機。 2. 基於金鑰的安全驗證 - 使用者將公鑰放在需要存取的伺服器上。 - 用戶端軟體發出請求時,會傳自己的公鑰和其他資訊給伺服器。 - 伺服器把存在伺服器與發送過來的公有密鑰進行比較。 - 如果兩個密鑰一致,伺服器就用公鑰加密「質詢」(challenge)並把它發送給用戶端軟體。 - 若用戶端成功解開質詢,回傳的資訊是與伺服器中的正確答案是相符的,則允許登入。 [^REF_sshauth]: [SSH的安全驗證 | 凌群電子報](https://www.syscom.com.tw/ePaper_Content_EPArticledetail.aspx?id=84&EPID...) by 鄭翔文 - 連線建立過程 (1)遠端主機收到使用者的登入請求,把自己的公鑰發給使用者。 (2)使用者使用這個公鑰,將登入密碼加密後,傳送回去給遠端主機。 (3)遠端主機用自己的私鑰,解密登入密碼,如果密碼正確,就同意使用者登入。 ![](https://i.imgur.com/OZNj39r.png) > 圖片來源 [鳥哥的 Linux 私房菜 伺服器建置實務-遠端連線伺服器 ssh 與 VNC](https://dic.vbird.tw/linux_server2/point04.php) :::info #### client-server model ![Client-server-model.svg](https://hackmd.io/_uploads/H1UjgI7g1x.png) > 圖片來源 [File:Client-server-model.svg](https://commons.wikimedia.org/w/index.php?title=File:Client-server-model.svg&oldid=928363449). 由 Calimo 以 David Vignoni 的 [Gnome-fs-client.svg](https://commons.wikimedia.org/wiki/File:Gnome-fs-client.svg), [Gnome-fs-server.svg](https://commons.wikimedia.org/wiki/File:Gnome-fs-server.svg) 為基礎來創作. Wikimedia Commons. - 主從(ㄗㄨㄥˋ)式架構 - **client** 特徵 - 主動的角色(主) - 發送請求 - 等待直到收到回應 - **server** 特徵 - 被動的角色(從) - 等待來自使用者端的請求 - 處理請求並傳回結果 ::: ### 基礎操作 #### 安裝 - 更新軟體的最新資訊及列表: `sudo apt update` - 安裝 server 端套件: `sudo apt install openssh-server` - 同時安裝 server 及 client: `sudo apt install ssh` :::info #### Appendix - ssh 好多種? - `apt-cache search [keyword]` 找軟體指令 - ![](https://hackmd.io/_uploads/r1GbPzn-p.png) - 可以觀察到有許多 ssh ,可以注意到以下這三種 - `openssh-client` - `openssh-server` - `ssh` (metapackage) - `openssh-server` for server ,必須等待來自使用者端的請求,所以於遠端的主機必須要有 ssh-server - 而 `openssh-client` 只負責發送資訊給 server 對應的 port - ssh (metapackage) 則是包含 client and server - metapackage 表示它不包含任何軟體安裝檔,它是導向到所需的相依安裝檔 - 把使用 ssh 完整服務所需要的所有檔案都安裝 - 延伸閱讀:[MetaPackages - Community Help Wiki](https://help.ubuntu.com/community/MetaPackages) - `openssh-client` 於 Ubuntu 中已內建,如果沒有要做連入的主機可以不安裝 `openssh-server` > P.S: Windows 10 1809 的 cmd 中也內建了 openssh-client ::: #### 確認 server 狀態 - 查看服務狀態 - `sudo systemctl status ssh` - 查看 ssh 佔用 port - `sudo ss -ltpn` - `-l`: 列出傾聽狀態(listening)的 sockets[^list_ports] - `-t`: 只列出 TCP 的 sockets - `-p`: 顯示使用 sockets 的程式資訊 - `-n`: 不要嘗試把 port 號解析成服務名稱 [^list_ports]: [使用 ss 指令檢查 Linux 網路 Socket 狀態資訊教學 – G. T. Wang](https://blog.gtwang.org/linux/socket-statistics-ss-command-tutorial/) #### 開啟關閉與重啟 server - `sudo systemctl start ssh` 開始 - `sudo systemctl stop ssh` 停止 - `sudo systemctl restart ssh` 重新啟動;關掉再打開 #### 由 client 登入 - 登入本機 - `ssh localhost` - `ssh 127.0.0.1` - `ssh [username]@127.0.0.1` - 本機地址 / 局部回送位址 (local loopback addresses) - 通常 `localhost` 會被解析成 `127.0.0.1` - 見 `/etc/hosts` 檔案 - IP 中 `127.0.0.1/8` 被設定為保留地址,所有向這個 IP 發送的封包都會留在本機 - 而 localhost 被作為頂級域名,不得有任何網域註冊此名稱 - 登入遠端 - `ssh [username]@[hostname]` - 不指定使用者則以目前狀態的使用者進行遠端登入 #### 常用操作參數 - `ssh -p [port num] [username]@[hostname]` 指定 server 的 port 號(預設 22) - server 端可以在設定檔中改變 port 號,如 port 號被更改就需要利用此方式登入 - `ssh [username]@[hostname] '[cmd]'` 執行單行指令 - ![](https://hackmd.io/_uploads/SJ7BnLgfp.png) - `ssh -f [username]@[hostname] '[cmd]'` 背景執行指令 - 即送出指令後可在原本的本機做事情 - `ssh -v [username]@[hostname] ` 使用偵錯模式連線 - 可使用 `-vv`、`-vvv`,v 越多,過程顯示的越多 - 有問題可以去看出了什麼問題 - `exit` / `logout` / `Ctrl+D` 退出連線 - `ssh -A` 允許 Forward agent :::spoiler 點此展開進階用法,暫時略過 > FIXME: 可能要加一下 -A 和 -X 成功的 demo - `ssh -X` 允許遠端打開圖形化介面視窗 > FIXME: -X 可能會無法運作,理解一下原因以及解法 > Ref: [xorg - X11 forwarding - Putty - Xming: Why app run on the server instead of the client side? - Super User](https://superuser.com/questions/1843704/x11-forwarding-putty-xming-why-app-run-on-the-server-instead-of-the-client) > Ubuntu 22.04 預設是 Wayland,而不是 X server - `ssh -o` 根據 ssh_config 做單次的設定 - `ssh -o ConnectTimeout=3 [username]@[hostname]` 等待時間如果超過三秒即斷線 ::: ### 密碼登入 - 流程圖[^ref_ssh1][^ref_ssh2] - ![](https://hackmd.io/_uploads/B1pHVWkGT.png =600x) > 流程圖來源:1121 LSA-I Week 08 [Linux 遠端連線](https://hackmd.io/@wzray07/HJN8ChbC3#%E5%AF%86%E7%A2%BC%E7%99%BB%E5%85%A5) 講義 by @wzray07 1. Client 請求登入,Server 回覆版本以及加密協議 2. Session Encryption Negotiation,進行密鑰協商 4. 密鑰協商後的 key 為最終資料傳輸的金鑰 5. Server 發公鑰給 Client,讓 Client 比對 Server 的身分 6. 上一步沒問題,使用者輸入帳密後,Cliient 將密碼使用 server 的公鑰加密後傳輸給 server 7. 最後雙方再以協商的密鑰,接收登入訊息並開始操作系統 [^ref_ssh1]: [SSH加密過程 - HackMD](https://hackmd.io/@yanren1996/rk9OUfY1i) by @yanren1996 [^ref_ssh2]: [Understanding the SSH Encryption and Connection Process | DigitalOcean](https://www.digitalocean.com/community/tutorials/understanding-the-ssh-encryption-and-connection-process) by Justin Ellingwood ### 利用公鑰進行無密碼登入 1. 在自己的用戶端 (client) 電腦上,產生一組金鑰對: 公開金鑰 (public key) / 私密金鑰 (private key) - `ssh-keygen -t ed25519` - `-t`: 指定用哪種加密方式,預設為 rsa - `-b`: 指定要生幾 bits 的金鑰 (不一定需要這參數) - 以安全性推薦使用 ed25519 代替 rsa,但舊的伺服器可能只支援 rsa - 輸出: ``` $ ssh-keygen -t ed25519 Generating public/private ed25519 key pair. Enter file in which to save the key (/home/user/.ssh/id_ed25519): /home/user/.ssh/id_ed25519_lsademo Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in /home/user/.ssh/id_ed25519_lsademo Your public key has been saved in /home/user/.ssh/id_ed25519_lsademo.pub The key fingerprint is: SHA256:icqDAThC3dD/aQItF7e5ZU4n0vXgn4ot3JvxicYtEjI user@host The key's randomart image is: +--[ED25519 256]--+ | ...+ | |o . o . . o | |= o o + o o | |.o o = = * o . | | . = S O o . .| | + . . E o o | | . + o + *.o | | . = B=..| | ++oo | +----[SHA256]-----+ ``` - 會問你要存在哪個位置,若不輸入直接按 Enter 則採用預設位置: - 私鑰會存在 `~/.ssh/id_ed25519` -> 自己留著,不能給別人的 - 公鑰會存在 `~/.ssh/id_ed25519.pub` -> 傳給別人的 - 若遇到檔名已存在,輸入 `y` 會覆蓋過去 ``` /home/user/id_ed25519 already exists. Overwrite (y/n)? y ``` - passphrase 可輸可不輸 - 若不輸入直接按 Enter 則無 passphrase - 若有設則後續每次使用此金鑰都會問你這段密碼 - 但現代一點的 OS 會有 ssh-agent 幫你暫時記住 - Fingerprint / randomart - 舊版本只有 Fingerprint 供大家可以連線時核對,但要檢查一長串文字不太容易[^Random_art] - 新版本更新成隨機圖像樣式,讓大家在連線時核對更方便 - 如何核對? - `ssh -o VisualHostKey=yes [username]@[hostname]` [^Random_art]: [ssh-keygen 在建立金鑰時所產生的 randomart 是做什麼用的? – G. T. Wang](https://blog.gtwang.org/tips/ssh-keygen-randomart/) :::info #### RSA 和 ED25519 差別 - `rsa` 預設 - **R**ivest–**S**hamir–**A**dleman,3 個人名組成的縮寫 - 相容性最好,支援稍舊的版本 - 密碼長度可選擇 `1,024` ~ `16,384` bits ,現在預設為 `3072` bits - `2048` bits 以下都不建議用,如需提升安全性可選擇更長的 key ,如:`3,072` 或 `4,096` bits (詳見文末延伸閱讀連結) - 若選擇 `3072` bits,公鑰會被 OpenSSH 編碼成 `544` 個 16 進位字元(chars) - `ed25519` 較推薦使用 - 較新,OpenSSH 6.5 版本以後就都支援[^REF_Crypto2] - 安全性最好 - 更快的產生金鑰 - 更快的身分驗證 - 長度固定 - 公鑰 `256` bits,被 OpenSSH 編碼成 `68` 個 16 進位字元(chars) - 是使用 SHA-512(SHA-2)和 Curve25519 的 EdDSA 簽名方式 - 扭曲的愛德華茲曲線 - `ecdsa` - 有 `256`, `384`, `521` bits 三種 key 長度可以選擇,無法選擇其他的使用 - 公鑰長度相比 RSA 較小[^REF_Crypto1] - 應用了**橢圓曲線加密法** [^REF_Crypto1]: [Day 24. 非對稱式加密演算法 - 橢圓曲線密碼學 Elliptic Curve Cryptography , ECC (觀念篇) - iT 邦幫忙::一起幫忙解決難題,拯救 IT 人的一天](https://ithelp.ithome.com.tw/articles/10251031) by 羊小咩 (lamb_mei) [^REF_Crypto2]: [選擇 SSH key 的加密演算法. 在 ssh-keygen 的 man page 說明中有一個… | by Chris Yuan, 袁昇禾 | Medium](https://medium.com/@honglong/%E9%81%B8%E6%93%87-ssh-key-%E7%9A%84%E5%8A%A0%E5%AF%86%E6%BC%94%E7%AE%97%E6%B3%95-70ca45c94d8e) ::: 2. 把公鑰複製到遠端主機 server 上 - 方法一 - 用 ssh-copy-id 傳送公鑰到遠端主機 `ssh-copy-id -i ~/.ssh/id_ed25519.pub [username]@[hostname]` * 方法二,手動複製 1. 先用帳號密碼登入遠端主機 server 2. `cd ~/.ssh` 3. 在遠端主機新增檔案 `touch authorized_keys` 4. 將 `id_ed25519.pub` 公鑰內容放入 `authorized_keys`中,以換行方式區分不同支公鑰 `vim authorized_keys` 5. `chmod -R go= ~/.ssh` 把這個資料夾中所有檔案的 group 及 other 權限拿掉 3. client 直接 ssh 到遠端主機 server - 採用預設 key: `ssh [username]@[hostname]` - 或自行指定 key: `ssh -i ~/.ssh/id_ed25519 [username]@[hostname]` - 若是 client 第一次連到這台 server,會輸出: ``` $ ssh username@remote_host The authenticity of host '203.0.113.1 (203.0.113.1)' can't be established. ECDSA key fingerprint is fd:fd:d4:f9:77:fe:73:84:e1:55:00:ad:d6:6d:22:fe. Are you sure you want to continue connecting (yes/no)? yes ``` - 意思是你的 client 還不認識這台 server。輸入 `yes` 後按 Enter 即可繼續連線 :::info 若遇到權限問題,用 `chmod 600 ~/.ssh/authorized_keys` ::: :::info #### 更換 ssh-server 公鑰[^Remove_REF] - 為了讓大家得知什麼樣的情況會跳出警告 - 先關閉 ssh 服務 &gt; 做任何相關設定檔調整前建議關閉服務再進行調整 - `sudo rm /etc/ssh/ssh_host*` 刪除 - ![](https://hackmd.io/_uploads/Hy0MNvAbp.png =500x) - `sudo dpkg-reconfigure openssh-server` 重新設定 - ![](https://hackmd.io/_uploads/S1WrNPRZp.png =600x) - 再把 ssh 服務開啟 - 試著用連線過的 client 去連線 - ![](https://hackmd.io/_uploads/B1EerP0ba.png =500x) - 因為公鑰已經被換過,所以比對的時候發現不一樣 - 解決辦法: - `ssh-keygen -f "~/.ssh/known_hosts" -R "[hostname]"` - ![](https://hackmd.io/_uploads/H1wxODRbp.png =500x) - 或是手動刪除也可以 - 根據警告提示行數刪掉 - Tips: 有時 SSH 升級時也會發現公鑰被替換的警告畫面,很可能是因為發現加密的密鑰存在漏洞,所以進行替換 > 手動刪除不會紀錄在 `known_host.old` 中 ::: [^Remove_REF]: [Ubuntu / Debian Linux 重新產生 OpenSSH Host Keys 的方法 | The Will Will Web](https://blog.miniasp.com/post/2010/08/30/Ubuntu-Debian-Linux-Regenerate-OpenSSH-Host-Keys) ### Forward Agent - ![](https://hackmd.io/_uploads/B1dy17-G6.png =400x) > 圖片來源 [SSH 免除重複輸入金鑰密碼教學:SSH Agent 與 Forwarding – G. T. Wang](https://blog.gtwang.org/linux/using-ssh-agent-forwarding-to-avoid-being-asked-passphrase/) - 範例狀況:client 端是員工筆電,Server A 與 Server B 為公司 Server - Server A 無法使用金鑰登入 Server B,密碼驗證也被關閉 - Server B 設定不允許任何外部 IP 連入 - Server B 擁有 Client 的公鑰 &gt; 實例: Server A 為網站 Server , Server B 為公司用機 &gt; 網站要做部署,要從 Server B 拿資料,但員工遠端工作在家 - 使用 Agent Forwarding 可解決 - client 端可以使用金鑰登入 Server A 與 Server B,但因為 Server B 不允許外部連入 - client 端登入 Server A 時將 SSH Key 一起轉給 A ,A 就可以利用 client 的 Key 登入 B ### ssh 相關設定檔案 - 設定檔中 `#` 為註解,且註解後通常為藍字 - 註解的內容為預設內容 - ssh 相關設定檔案 `/etc/ssh/` #### Client - `/etc/ssh/ssh_config` - ![](https://hackmd.io/_uploads/S1oowgbMp.png =500x) :::spoiler 文字版 ```config Include /etc/ssh/ssh_config.d/*.conf Host * # ForwardAgent no # ForwardX11 no # ForwardX11Trusted yes # PasswordAuthentication yes # HostbasedAuthentication no # GSSAPIAuthentication no # GSSAPIDelegateCredentials no # GSSAPIKeyExchange no # GSSAPITrustDNS no # BatchMode no # CheckHostIP yes # AddressFamily any # ConnectTimeout 0 # StrictHostKeyChecking ask # IdentityFile ~/.ssh/id_rsa # IdentityFile ~/.ssh/id_dsa # IdentityFile ~/.ssh/id_ecdsa # IdentityFile ~/.ssh/id_ed25519 # Port 22 # Ciphers aes128-ctr,aes192-ctr,aes256-ctr,aes128-cbc,3des-cbc # MACs hmac-md5,hmac-sha1,umac-64@openssh.com # EscapeChar ~ # Tunnel no # TunnelDevice any:any # PermitLocalCommand no # VisualHostKey no # ProxyCommand ssh -q -W %h:%p gateway.example.com # RekeyLimit 1G 1h # UserKnownHostsFile ~/.ssh/known_hosts.d/%k SendEnv LANG LC_* HashKnownHosts yes GSSAPIAuthentication yes ``` ::: - ForwardAgent 驗證代理 - 讓本地 SSH Key 可由遠端 server 轉送 - IdentityFile - 指定要用哪個私鑰 - PasswordAuthentication - 允許 / 不允許 client 使用密碼登入 ssh server - CheckHostIP - 確認已連線過的主機是否有 IP 不同的問題,發現就提醒 - ConnectTimeout - 連線超過指定秒數就斷線 - Port - 預設使用 22 port 進行連線 - 針對指定 Server 做此設定 - 例如 ```conf= Host ec2 User lsa Port 22 Hostname lsalab.moli.rocks ``` - 如此在下 `ssh ec2` 指令時,會採用以上設定連線 - 可放置在 `/etc/ssh_config` 中,也可以建立一個檔案 `~/.ssh/config` #### Server - `/etc/ssh/sshd_config` - **基礎設定** - ![](https://hackmd.io/_uploads/SypzHWWGa.png =500x) :::spoiler 文字版 ``` #Port 22 #AddressFamily any #ListenAddress 0.0.0.0 #ListenAddress :: #HostKey /etc/ssh/ssh_host_rsa_key #HostKey /etc/ssh/ssh_host_ecdsa_key #HostKey /etc/ssh/ssh_host_ed25519_key ``` ::: - Port 選擇使用 port 號 (預設 22 ) - ListenAddress 允許連入的 IP address 預設 `0.0.0.0` 為 IPv4 中允許主機所擁有的任何 IP 連入 - `::` 為 IPv6 中,允許主機所擁有的任何 IP 連入 - HostKey 存放私鑰位置 - **認證相關** - ![](https://hackmd.io/_uploads/SJoF4WWzp.png =600x) - PermitRootLogin - 是否允許使用 root 登入(預設為禁止使用密碼登入) - PubkeyAuthentication - 是否允許使用 Public Key 登入 (預設為 yes) - PasswordAuthentication ⭐ - 是否允許 client 使用密碼登入(預設為 yes) - 若設 `no` ,剩下 public key 驗證模式,可大大降低猜密碼攻擊危險性 - PermitEmptyPasswords - 是否允許輸入空密碼登入(預設為 no) - 針對單獨 client 設定 - Match User anoncvs - 如果你只想針對某用戶進行特殊設定,可使用這個功能 ```conf= Match User ray PasswordAuthentication no ClientAliveInterval 30 ClientAliveCountMax 20 ``` - 針對 client 端叫 ray 的人給他這樣的設定 :::info #### SSH config include 設定 - 觀察檔案會有一行 - ![](https://hackmd.io/_uploads/HyZsJfWMT.png =300x) - 在 `/etc/ssh/` 中會發現有一個目錄 `sshd_config.d` - 用來存放使用者想更動的設定,為了防止 sshd_config 被改壞 - ssh 在運作時更改設定很可能會出問題,所以建議是以關閉狀態改變設定或是在這個目錄新增 `.conf` 檔去做設定 ::: ## 遠端檔案傳輸 ### FTP - File Transfer Protocol - 古老的檔案傳輸協定 - 明文傳輸 (沒有加密) 方式 - client 可以把檔案**上傳至 / 下載 from** ftp server - 優點 - 傳輸速度快 - 與 HTTP 相比,他不需要包很多 Header ,所以封包自然也就比較輕 - 缺點 - 傳輸不安全 - 如需登入帳密會有安全性問題 - port 號 - 20 port 資料連線通道 - 21 port 控制連線通道 - 雖然不安全,但如果是公共檔案就比較沒有問題 - 安裝檔、給大家的~~作業~~文件, etc. - 可匿名使用 - 雖可匿名,但仍會紀錄登入請求來源 #### FTP Server - 常見: vsftpd、proftpd - 以下用 vsftpd 示範 - `sudo apt install vsftpd` - `sudo service vsftpd status` - ![](https://hackmd.io/_uploads/rk9gCP0fp.png) - 安裝後確認 - `/etc/vsftpd.conf` 設定檔位置 - 以下介紹匿名模式的設定(不建議大家利用 ftp 傳送重要檔案) - ![](https://hackmd.io/_uploads/S1tbW_0f6.png) :::info ## 參數參考 - `anonymous_enable=YES (NO)` - 是否允許匿名者 - `anon_other_write_enable=YES (NO)` - 匿名者是否有寫入檔案的權限(預設為 NO ) - `anon_mkdir_write_enable=YES (NO)` - 匿名者是否有目錄創建的功能(預設為 NO ) - `anon_upload_enable=YES (NO)` - 匿名者是否有上傳檔案的功能 - `no_anon_password=YES (NO)` - 匿名者登入是否需要密碼,預設為 NO ,需要密碼 - `anon_root = /var/ftp/` - 匿名者登入初始路徑 - `guest_enable=YES (NO)` 與 `local_enable=YES (NO)` - 如不允許實體用戶即可設定為 NO - **如果沒有設定參數需自行加進 conf 檔** ::: > FIXME: 開設定好匿名上傳下載的 server 給大家玩? - 完成設定後,重啟 service - 重啟 service 後可以先登入本機測試 - ![](https://hackmd.io/_uploads/SJWFSO0fT.png) - 輸入 `anonymous` 表示匿名登入 - 密碼可以選擇不輸入(不過密碼會紀錄) - 紀錄檔 `/var/log/vsftpd.log` - ![](https://hackmd.io/_uploads/BylvOdRGT.png) #### FTP 操作[^REF_FTP] - `ftp [ip address]` 登入 - 如果是公眾的 server,username 可輸入`anonymous`作為匿名,密碼可空白 - `put [client_file] [server_pwd] ` 上傳檔案,如 server 上已有重複的檔案則覆蓋 - `get [file] [client_pwd]` 下載檔案,如 client 上已有重複的檔案則覆蓋 - `ls` 與 Linux 指令一樣, list - `cd` 與 Linux 指令一樣, change directory - `lpwd` 顯示本機端目前位置 - `lcd` 切換本機端位置 - `help` 查看更多指令 - `bye` 退出 [^REF_FTP]: [Linux ftp 指令 - Linux 技術手札](https://www.hkcode.com/linux/linux-ftp-command) ### SFTP - **S**SH **F**ile **T**ransfer **P**rotocol - client 指令基本上與 FTP 語法一樣,只是 SFTP 是 SSH 的一部分 > 所以 server 端需要 SSH 才能使用 :::info 在 **sshd_config** 檔案中,有 ```config # override default of no subsystems Subsystem sftp /usr/lib/openssh/sftp-server ``` ::: - 利用 SSH 傳輸,所以預設與 SSH 一樣使用 22 port - 解決 FTP 明文傳輸的問題 - 效率 - FTP &gt; SFTP - 安全性 - FTP &lt; SFTP - 登入 - `sftp [user]@[hostname]` ### SCP - **S**SH copy <!-- 不一定是 SSH backend? --> - `cp` 在 Linux 是複製 - 而 `scp` 為遠端複製檔案 #### scp 操作[^REF_SCP] - 用法 - `scp [參數] [source] [destination]` - 從本機上傳至遠端 - `scp [本機檔案路徑] [usr_name]@[hostname]:[遠端檔案路徑]` - `path` 不輸入則為家目錄 - 從遠端下載到本機 - `scp [usr_name]@[hostname]:[遠端檔案路徑] [本機檔案路徑]` - `-r`: recursive ,目錄中所有檔案 - `scp [folder]/** [destination]` [^REF_SCP]: [Linux 的 scp 指令用法教學與範例:遠端加密複製檔案與目錄 – G. T. Wang](https://blog.gtwang.org/linux/linux-scp-command-tutorial-examples/) ### Rsync - Rsync 能做到 `cp` 跟 `scp` 的事,但 Rsync 的效率比 `cp` 跟 `scp` 好 - 靈活性高 - 除了複製檔案,也非常適合用來作備份工具 - 可使用於本機與遠端 - 支援連結檔與設備檔 - 支援複製後保留檔案的屬性(擁有者、群組與權限設定) - 在第一次複製檔案時,會複製完整的檔案內容 - 如複製時發現有一樣檔案在裡面,會利用 delta-transfer 演算法**檢查新舊檔案之間的差異,只傳送有變動的部份** - 節省複製的時間,可加快備份速度(大檔案傳輸時會有更明顯的差異) - 進行遠端傳輸時,可節省網路頻寬 - 支援資料的自動壓縮與解壓縮,也可節省網路頻寬 #### rsync 操作 [^Rsync_REF1][^Rsync_REF2] - 為內建工具,但如果沒安裝 - `sudo apt install rsync` #### 基礎語法 - `rsync [參數] [來源檔案] [目的檔案]` #### 常見參數 | 參數 | 說明 | | ----------------------- |:-------------------------------------------------------------------------------------------------- | | `-v` | verbose 模式,輸出比較詳細的訊息 | | | `-a` | 封裝備份模式,遞迴備份所有子目錄下的目錄與檔案,保留連結檔、檔案的擁有者、群組、權限以及時間戳記。 | | `-z` | 啟用壓縮。 | | `-h` | 將數字以比較容易閱讀的格式輸出。 | | | `-P` / `--progress` | 顯示傳輸進度 | | `--delete` | 同步將不存在於來源端的檔案刪除 | #### 常見使用情境 #### 基本本機複製 - `rsync -avh /home/wzray/a/ /home/wzray/b/` - `-a` 這個參數包含 `-r`,所以要複製整個目錄下的檔案也沒問題 - `rsync -avh /home/wzray/a/ /home/wzray/b/` - 試著修改一個檔案,再敲一次指令後,觀察他處理了什麼檔案 - ![](https://hackmd.io/_uploads/B1XrvtRzp.png =500x) #### 遠端備份 - 本機 => 遠端 - `rsync -avzh ~/file wzray@192.168.1.12:/home/wzray/` - 遠端 => 本機 - `rsync -avzh wzray@192.168.1.12:/home/wzray/ ~/file` - 跟 `scp` 語法很像 #### 同步刪除檔案 - 如果第二次複製時發送端的部分檔案已刪除,想要在目的端同步刪除該檔案 - `rsync -avh --delete /home/wzray/a/ /home/wzray/b/` [^Rsync_REF1]: [Linux 使用 rsync 遠端檔案同步與備份工具教學與範例 – G. T. Wang](https://blog.gtwang.org/linux/rsync-local-remote-file-synchronization-commands/) [^Rsync_REF2]:[rsync & scp - HackMD](https://hackmd.io/@celineyeh/ByHCum98B) by 葉佳臻 @celineyeh ## SSH Tunnel - 基於 SSH Protocol 所延伸的技術 - 將網路上的 A、B 兩個端點用 Tunnel 連接起來,形成一個**隧道** - 基本過程: - A 點上的某個 Port X 所傳送的資料轉送 至 B 點上的 Port Y - 又被稱 Port Forwarding - **好處** - 可突破防火牆限制 - 如防火牆有擋掉特定 port , 沒有擋掉 22 port ,可利用此種方式穿透此限制 - 將通訊內容加密避免洩漏 - 利用 SSH 加密特性來進行通訊 - Tunneling 中通常會出現以下三種角色 - **Client** - 任何你可以敲 ssh 指令來啟動 Port Forwarding 的機器 - **SSH Server** - 可以被 Client 用 SSH 連進去的機器 - **Target Server** - 某一台你想建立連線的機器,通常是為了對外開放這台機器上的服務 - Client 與 SSH Server 本身都可以是 Target Server ,不是真的要有三台機器才可以進行 Port Forwarding! ### Local Port Forwarding - 語法 - `ssh -L [bind_address:][port]:[host]:[host_port] [SSH Server]` - `[bind address:]` 不輸入預設為 `localhost` - **情境一:** - ![](https://hackmd.io/_uploads/B1AfAd7fT.png) - 防火牆後有一台 Server ,但防火牆設定不接受 8080 port 連入,不過接受 22 port - 使用 tunneling 將 client 中的某個 port (圖中範例 port 9090),對他發送的資料經 SSH 通道轉送至 8080 port,等於連上 client 9090 port 就可以連上 Server 8080 port ,完成繞過防火牆限制 - ![image](https://hackmd.io/_uploads/S1wAKUDgyg.png) - `ssh -L 9090:localhost:8080 [username]@[server]` - **Client** - 你的電腦 - **SSH Server** - 防火牆後的 Server - `[username]@[server]` - **Target Server** - 防火牆後的 Server - localhost:8080 &gt; `bind address`沒輸入代表使用預設 `localhost` &gt; 如果要開放對外可以改成 `0.0.0.0` &gt; `host` 的 `localhost` 是只針對 `server` 的 `localhost` - **情境二:** - ![](https://hackmd.io/_uploads/r1R2IUCza.png) - 前面情境為 Server 能連入的情況,那如果今天權限不足以連入要怎麼辦 - 如果防火牆後有一台你的機器且可用 ssh 連入即可完成 :::spoiler - ![](https://hackmd.io/_uploads/S1wRPLAfa.png) ::: - ![](https://hackmd.io/_uploads/r1FbcUwl1e.png) - `ssh -L 9090:192.168.2.10:8080 [username]@[server]` - **Client** - 你的電腦 - **SSH Server** - 你的機器 - `192.168.2.10:8080` - **Target Server** - 防火牆後的 Server - `[username]@[server]` ### Remote Port Forwarding - 語法 - `ssh -R [bind_address:][port]:[host]:[host_port] [username]@[server]` - **情境一:** - ![](https://hackmd.io/_uploads/H1Dn_YXMT.png) - 你的電腦上完成了一個服務,並架上 8080 port ,但你的電腦沒有對外 ip,僅有內部 ip - 準備一台有 Internet 的機器當作對外機器,即可使用 Remote Forwarding 完成 - 對外機器開啟一 port 客戶連入 (圖片範例 port 9090) - 對外機器藉由 SSH 通道將轉送到 port 8080,客戶即可取得服務 - ![](https://hackmd.io/_uploads/S1KIjtXfa.png) - `ssh -R 0.0.0.0:9090:localhost:8080 [username]@[SSH Server]` - 因為要開放對外,所以設定`0.0.0.0` - `localhost` 是針對你的電腦 - **Client** - 你的電腦 - **SSH Server** - 對外機器 - `[username]@[server]` - **Target Server** - 你的電腦 :::warning - 基於安全考量,Remote Forwarding 的預設都只能夠 bind 在 SSH Server 的 localhost 上 - 所以必須要改變設定 - 至 sshd 內的設定檔 - `GatewayPorts yes` ::: - **情境二:** - ![](https://hackmd.io/_uploads/Byzqeq7Ga.png) - 與情境一不同,服務另外架在其他機器上 - 一樣也可以使用 Remote Forwarding - ![](https://hackmd.io/_uploads/Bk45G9mza.png) - `ssh -R 0.0.0.0:9090:192.168.1.100:8080 [username]@[SSH Server]` - `192.168.1.100` 為內部服務 ip(相對於你的電腦) - **Client** - 你的電腦 - **SSH Server** - 對外機器 - `[username]@[server]` - **Target Server** - 內部服務 - `192.168.1.100:8080` ### Dynamic Port Forwarding - 語法 - `ssh -D [bind_address:][port] [username]@[SSH Server]` - 情境 - ![Untitled Diagram-Page-6.drawio (1).png](https://hackmd.io/_uploads/rk4uPXUmT.png) - 只要有一台位於內網且具有外部 IP 的機器,你就可以利用這個方法建立一個 SOCKS 代理伺服器,讓你能夠從外面連回內網裡的所有服務 [^port_fwd_1][^port_fwd_2_img_src] [^port_fwd_1]: [使用SSH Tunnel提供更安全的存取通道 | 恆逸講師技術文章發表UCOM TIPS](https://www.uuu.com.tw/Public/content/article/17/170320tips.htm) by 陳勇勳 [^port_fwd_2_img_src]: [SSH Tunneling (Port Forwarding) 詳解 · John Engineering Stuff](https://johnliu55.tw/ssh-tunnel.html) > FIXME: 三種 tunnel 模式想個 demo > FIXME: 線要畫確實,包括從哪進、從哪出,下面幾張圖亦然 ## 補充資料 - [如何讓兩台虛擬機可以用 ssh 連線 - HackMD](https://hackmd.io/@oJ7l_4AbTkCmGKJnAmApWw/ryXtBNePF) - [遠端連線虛擬機 - HackMD](https://hackmd.io/@wzray07/Bkhh64xGT) ## 延伸閱讀 [cryptography - SSH Key: Ed25519 vs RSA - Information Security Stack Exchange](https://security.stackexchange.com/questions/90077/ssh-key-ed25519-vs-rsa) [EdDSA - 維基百科,自由的百科全書](https://zh.wikipedia.org/wiki/EdDSA#Ed25519) 當中的 Ed25519 章節 ## 參考資料 - 1121 LSA-I Week 08 [Linux 遠端連線 - HackMD](https://hackmd.io/@wzray07/HJN8ChbC3) by Ray @wzray07 - 1111 LSA-I Week 06 [Linux ssh 遠端連線 - HackMD](https://hackmd.io/7kiV5QwqT3y7L46EZF8DQQ?view) by @Alanjy-Huang - [OpenSSH Server | Ubuntu](https://ubuntu.com/server/docs/openssh-server) - [How to Set Up SSH Keys on Ubuntu 22.04 | DigitalOcean](https://www.digitalocean.com/community/tutorials/how-to-set-up-ssh-keys-on-ubuntu-22-04) by Alex Garnett - 國家教育研究院 [樂詞網 : 局部回送位址](https://terms.naer.edu.tw/detail/f76cc81a062b80afb496c8c94b5329f4/?startswith=zh&seq=20) - [Introduction | Ed25519: high-speed high-security signatures](https://ed25519.cr.yp.to/) - [使用 ss 指令檢查 Linux 網路 Socket 狀態資訊教學 – G. T. Wang](https://blog.gtwang.org/linux/socket-statistics-ss-command-tutorial/) - [Day18- Diffie–Hellman - iT 邦幫忙::一起幫忙解決難題,拯救 IT 人的一天](https://ithelp.ithome.com.tw/articles/10294073) by nynapig - [An Illustrated Guide to SSH Agent Forwarding](http://unixwiz.net/techtips/ssh-agent-forwarding.html) 較簡易的圖解 - [RFC 4251 - The Secure Shell (SSH) Protocol Architecture](https://datatracker.ietf.org/doc/html/rfc4251) - [RFC 4252 - The Secure Shell (SSH) Authentication Protocol](https://datatracker.ietf.org/doc/html/rfc4252) - [RFC 4254 - The Secure Shell (SSH) Connection Protocol](https://datatracker.ietf.org/doc/html/rfc4254)