###### tags: `lsa` # Linux 遠端連線 [TOC] ## Preface ### 指令複習 :::spoiler - `sudo` ?? - 什麼時機需使用 `sudo` - 如何查看網路狀態 - 如何查看 ip ::: ### 使用情境 - 跟計中借 Server,使用要一直去計中操作嗎? - 想使用 Server 但不想去機房操作 - 想使用家裡的高級電腦 - 在家辦公但是檔案在公司?? > Server 有別於一般家用電腦,主要目的為了提供服務以及資料處理 > 主要為企業或組織提供服務用 ### 工具類型 - 文字介面明碼: telnet, rsh 等為主,目前非常少用 (取得 Shell) - 文字介面密碼: ssh 為主,已經取代上述的 telnet, rsh 等明碼方式 (取得 Shell) - 文字介面:遠端取得 Shell - 圖形介面: Xdmcp, VNC, RDP 等較為常見 (GUI 介面) > FIXME: FileZilla - ![](https://hackmd.io/_uploads/ryz5jIeka.png =500x) > [REF From 鳥哥](https://linux.vbird.org/linux_server/centos6/0310telnetssh.php) > [REF From iThome](https://ithelp.ithome.com.tw/articles/10277498) ## 遠端連線協議 (SHELL) ### Telnet <!-- - TCP/IP 中屬於 Application Layer 中的一種協議 --> - 支援的使用者軟體比較多 - 傳輸資料時未加密 (明文傳輸) - 有心人士擷取封包 => 裸奔的資料 (帳號密碼) - 沒有驗證機制,無法保證是否為本人發送 > ![](https://hackmd.io/_uploads/HJQU0ls03.jpg =600x) - 連線流程: - 終端使用者(本機)與遠端伺服器建立連線,port 號為 23 號 - 終端使用者進行遠端伺服器帳號密碼登入 - 遠端伺服器回應終端使用者 - ![](https://hackmd.io/_uploads/Byu2rZi0n.png) > [REF](https://gordonfang-85054.medium.com/telnet%E5%B0%81%E5%8C%85%E5%AF%A6%E6%88%B0-e9306216fba0) > Demo :::info <!-- ## Appendix - TCP/IP - TCP/IP Protocol Suite 或 TCP/IP Protocols - TCP 傳輸控制協定 - IP 網際網路協定 - 裝置與裝置間進行通訊,須遵守的規則 - 如果裝置廠商沒有遵守可能就會造成無法通訊 - TCP/IP Model 可以分成四層 - Link Layer - Internet Layer - Transport Layer - Application Layer ![](https://hackmd.io/_uploads/Hkty_Q2A2.png) ![](https://hackmd.io/_uploads/HkJzi_2Ch.png) --> ## Port - 通訊埠 => 埠號 > 那個字念 ㄅㄨˋ - 在系統中扮演通訊端點 - 用於區分同一個 IP 地址下的**不同服務**,每個服務使用的 Port 皆不同 > 像是學校辦公室都有不同的處室在幫學生處理校務 ### 為什麼需要 port ? 1. 區分不同的服務 - 當封包傳回來,就能根據 port 來判斷這些資料應該傳送到哪個服務 2. 同時運行多個服務 - 由於每個服務都有自己的 port,能夠在同一時間傳送資料,而不會送錯 - 本來要傳給 telegram 的封包,結果被送到 line <!-- - **port 號規定** - 16 bits 表示,所以可以使用 2^16 (65536) 個 port - 0 為保留埠 `FIXME: 保留埠 v.s. 系統保留 ?` - 1~1023 為系統保留,大多為常見的通訊服務 `FIXME: 系統保留也可以使用, 但不推薦` - 剩餘的 port 號交由使用者自行分配 `FIXME: 舉個`:chestnut: `FIXME: 使用者分配 不是程式分配` --> ### port number - 範圍:從 0 ~ 65535 - 16 bits 表示,共有 65535 個 port (2^16) - ![](https://hackmd.io/_uploads/Sk9PhmAZT.png) - 常用的 port 會記錄在 `/etc/service` > Demo #### Well-Known Ports - 0 - 保留 port ,平常不會啟用 - 1 ~ 1023 需**超級使用者權限**才能占用這些 port > 範圍中的服務都是一些比較古老、對系統重要的服務 <!-- > `FIXME: 一個port可以提供多個process嗎? Nope, 辦不到的原因(要再去聽一次影片)` --> - ![](https://hackmd.io/_uploads/BkVeoXC-6.png) > [圖片來源](https://en.wikipedia.org/wiki/Port_(computer_networking)) - 由 IANA 進行管理和分配 #### Registered Ports - 1024 ~ 49151 - 公司或組織可以向IANA申請和註冊這範圍內的 port > 註冊的好處: 讓大家知道這個 port 有人用了,且這個服務是使用這個 port - 不需超級使用者權限 - 特定的服務 - MySQL database service (also for MariaDB) : 3306 #### Private/Dynamic Ports - 49152 ~ 65535 - 網路中的這些 port 未向 IANA 註冊 - 可以在 local 或由應用程式動態使用 > 雖然 Port 號劃分成以上這三種,但使用者仍然可以自行去改變服務中的 Port 號 > 也就是說 Registered Ports 的服務可以改成 Well-Known Ports ,只是不推薦 > 不推薦的原因: 1. 怕別人找不到地方連接 2. 避免多服務衝突 ## Appendix - IANA - Internet Assigned Numbers Authority - 非營利組織 - 定義 port number - 管理及維護 Domain Names、Number Resources、Protocol Assignments - ![](https://hackmd.io/_uploads/BkCPLLR-a.png) > [網站](https://www.iana.org/) ::: ### SSH - ![](https://hackmd.io/_uploads/S1tXYvqZT.png) > [source](https://codesorcery.net/2008/05/06/ssh-tunnels-for-the-common-man-and-woman.html) - **S**ecure **SH**ell Protocol - 解決 Telnet 明文傳輸的問題,更安全 > 美國中央情報局已經開發出能夠在 Windows 或 Linux 作業系統中竊取 SSH 對談的工具。[BothanSpy_REF](https://web.archive.org/web/20170708232957/https://wikileaks.org/vault7/#BothanSpy) - port 號預設 22 - 加密式連線 > 目前在 SSH 使用上,主要是利用 RSA/DSA/Diffie-Hellman 等機制 :::info ## Appendix - 加密式連線 - 將人看得懂的原始資料,經過演算法進行加密,變成人看不懂的亂碼後進行傳輸,而當接收端收到資訊想查閱時再進行解密。 > 情境例子:我為了不想讓周遭的人聽到我跟朋友的交談內容,我把我講的話翻譯成獨創語言,之後說給聽得懂獨創語言的朋友聽。 ### 常見加密方式 > 所以對稱、非對稱各自優缺差別在哪裡 #### 對稱式加密 - 接收端與發送端皆持有相同的密鑰,用來做加解密 - ![](https://hackmd.io/_uploads/rJ6xK99-p.png) > [REF](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) - **問題1**:如果密鑰被別人找到,則該中間人未來擷取到的加密訊息皆可隨意解密讀取。 - **問題2**:如果中間人將原本的加密資訊替換成加密過的惡意資訊,然而接收端未發現資訊被替換過,進而導致接收端被惡意攻擊 > 因此進而延伸出非對稱式加密 - **常見演算法**: AES(進階加密標準)、 DES (資料加密標準) > [REF_AES](https://zh.wikipedia.org/zh-tw/%E9%AB%98%E7%BA%A7%E5%8A%A0%E5%AF%86%E6%A0%87%E5%87%86) > [REF_DES](https://zh.wikipedia.org/zh-tw/%E8%B3%87%E6%96%99%E5%8A%A0%E5%AF%86%E6%A8%99%E6%BA%96) #### 非對稱式加密 - 一位使用者會有兩隻金鑰 - 公開金鑰 (Public Key):可給指定對象 - 私密金鑰 (Private Key):自己保留用 > 簡稱公鑰、私鑰 - 利用其中一隻進行加密,則一定要用另外一隻進行解密 - 公鑰加密私鑰解密 - 私鑰加密公鑰解密 > 兩模式皆可 > 就像兩人持有不同的翻譯機 > 我先拿了中翻英的系統加密,但一定要拿英翻中的系統才能解密 > 但公鑰是拿來傳給別人用的,所以私鑰加密公鑰解密這件事不會拿來加密訊息 > 加密數位簽章 - ![](https://hackmd.io/_uploads/Hk6DF65ba.png) - 首次傳輸,收件方會與寄件方交換公鑰 - 寄件方要發送資料,先利用收件者的公鑰進行加密,而收件方收到加密資料後再用自己的私鑰解密 - 收到資料了!這樣就結束?還有問題存在 - 如果中間人找到收件方的公鑰,則中間人就可以利用該公鑰加密惡意資訊並傳送給收件方,進而讓收件方受到惡意攻擊,無法驗證傳送者。 - **數位簽章**解決 - 對資料進行二次確認 - 寄件者除了要用收件者公鑰加密資料,寄件者使用自己的私鑰對該封加密訊息的 Hash 簽名 > Hash 雜湊函數 > 簡單來說就是加上了寄件者的簽章,而將 Hash 過的訊息當作簽章 - 到收件方除了利用自己的私鑰解密,也要用寄件者的公鑰進行簽章確認 - 就像是針對資料加密後再上一層指紋鎖 - 流程 - ![](https://hackmd.io/_uploads/Sk7hegDG6.png) - 兩個 雜湊數值相同即可證明是寄件人本人傳送 > [REF流程](https://aikawa0617.medium.com/%E5%AF%86%E7%A2%BC%E5%AD%B8-%E4%B8%89-%E6%95%B8%E4%BD%8D%E7%B0%BD%E7%AB%A0-f8c6a78da46b) > [REF_加密](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) ::: - SSH 發布過兩種版本 - V2.X 的版本改使用對稱式加密處理訊息,非對稱式加密處理驗證身份 - 大多都使用 V2 的版本 > [REF](https://www.syscom.com.tw/ePaper_Content_EPArticledetail.aspx?id=84&EPID...) #### 連線 - 以 client-server model 進行傳輸 - 主從(ㄗㄨㄥˋ)式架構 - **client 特徵** - 主動的角色(主) - 發送請求 - 等待直到收到回應 - **server 特徵** - 被動的角色(從) - 等待來自使用者端的請求 - 處理請求並傳回結果 - 我們通常都是扮演 client 的身份去連入 - ![](https://hackmd.io/_uploads/rJtiZfsbT.png) > [Img_src](https://zh.wikipedia.org/zh-tw/%E4%B8%BB%E5%BE%9E%E5%BC%8F%E6%9E%B6%E6%A7%8B) <!-- - client 端發送請求連線 - server 傳出自己的公鑰(明文傳輸) - client 拿到公鑰後存到 `~/.ssh/known-hosts` ,並運算自己的公鑰與私鑰 - 如果已經建立過則進行比對(即曾連線過) - 回傳 client 自己的公鑰 - 完成加密連線通道 - ![](https://hackmd.io/_uploads/SJaeXMoZ6.png) > [Img_and_ref_from_鳥哥](https://linux.vbird.org/linux_server/centos6/0310telnetssh.php#ssh_server) --> :::success ## 基礎操作 ### 進行操作前,請先完成以下設定 - [傳送門](https://hackmd.io/@wzray07/Bkhh64xGT) ### 安裝 - `sudo apt install openssh-server` - `sudo apt install ssh` ::: - server 初次完成安裝後,自動產生公鑰與私鑰並記錄於 `/etc/ssh/ssh_host_*` - ![](https://hackmd.io/_uploads/BJwk28C-p.png) > 多種加密方式 :::info ## Appendix - ssh 好多種? - `apt-cache search [keyword]` 找軟體指令 - ![](https://hackmd.io/_uploads/r1GbPzn-p.png) - 可以觀察到有許多 ssh ,可以注意到以下這三種 - `openssh-client` - `openssh-server` - `ssh` (metapackage) - client-server model - `openssh-server` for server ,必須等待來自使用者端的請求,所以於遠端的主機必須要有 ssh-server - SSH server 預設只聆聽 22 port - 而 `openssh-client` 只負責發送資訊給 server 對應的 port - ssh (metapackage) 則是包含 client and server - metapackage 表示它不包含任何軟體安裝檔,它是導向到所需的相依安裝檔 - 把使用 ssh 完整服務所需要的所有檔案都安裝 > [Metapackage_Ubuntu_DOC](https://help.ubuntu.com/community/MetaPackages) - `openssh-client` 於 ubuntu 中已內建,如果沒有要做連入的主機可以不安裝 `openssh-server` > P.S: Windows 10 1809 的 cmd 中也內建了 openssh-client ::: :::success ## 續-基礎操作 ### 確認狀態 - 查看服務狀態 - `sudo service ssh status` - 查看 ssh 佔用 port - 該如何查看呢?? ### 開啟關閉與重啟 - `sudo service ssh start` - `sudo service ssh stop` - `sudo service ssh restart` ### 登入 - 登入本機 - `ssh localhost` - `ssh 127.0.0.1` - `ssh [username]@127.0.0.1` - 本地環迴地址 - `127.0.0.1` == `localhost` - IP 中 `127.0.0.1/8` 被設定為保留地址,所有像這個 ip 發送的封包都會轉送到本機 - 而 localhost 被作為頂級域名,不得有任何網域註冊此名稱 - 登入遠端 - `ssh [username]@[user_ip]` - 不指定使用者則以目前狀態的使用者進行遠端登入 ### 常用操作參數 - `ssh -p [port num] [usr]@[ip adress]` 指定 server 的 port 號(預設 22) - server 端可以在設定檔中改變 port 號,如 port 號被更改就需要利用此方式登入 - `ssh [usr]@[ip adress] '[cmd]'` 執行單行指令 - ![](https://hackmd.io/_uploads/SJ7BnLgfp.png) - `ssh -f [usr]@[ip adress] '[cmd]'` 背景執行指令 - 即送出指令後可在原本的本機做事情 <!-- - 執行多行指令 - ![](https://hackmd.io/_uploads/SJTOT8xza.png) --> - `ssh -v [usr]@[ip adress] ` 使用偵錯模式連線 - 可使用 `-vv`、`-vvv`,v 越多,過程顯示的越多 - 有問題可以去看出了什麼問題 - `ssh -A` 允許 Forward agent > 後面會提到 - `ssh -X` 允許遠端打開圖形化介面視窗 - `ssh -o` 根據 ssh_config 做單次的設定 - `ssh -o ConnectTimeout=3 [usr]@[ip adress]` 等待時間如果超過三秒即斷線 - `exit` / `logout` / `Ctrl+D` 退出連線 ::: #### 密碼登入 - ![](https://hackmd.io/_uploads/B1pHVWkGT.png =600x) 1. Client 請求登入,Server 回覆版本以及加密協議 2. Session Encryption Negotiation,進行密鑰協商(Appendix) 3. 密鑰協商後的 key 為最終資料傳輸的金鑰 4. 發公鑰給 Client,並進行驗證機制 5. 驗證完沒問題輸入帳密後使用公鑰加密並傳輸給 server 登入 6. 最後用戶再以用戶私鑰解密,接收登入訊息並開始操作系統 > [REF1](https://hackmd.io/@yanren1996/rk9OUfY1i) > [REF2](https://www.digitalocean.com/community/tutorials/understanding-the-ssh-encryption-and-connection-process) > 流程圖來源:自己 :::info ## 密鑰協商:Diffie-Hellman 演算法 - ![](https://hackmd.io/_uploads/B1SBvZJzp.png) - 最終 `A^b mod P` 與 `B^a mod P` 結果應相等 - 所以密鑰相同,為對稱式加密 - 不過 A 與 B 挑的隨機數不同,可用來輔助對稱式加密 - 叫做非對稱式演算法 > 算式不用講 - 連完就丟,不重複連 - 外部的人只聽得到兩端所挑的數字,但這些資訊無法讓外人算出 key 是多少 > [img_src](https://hackmd.io/@yanren1996/rk9OUfY1i) ::: #### SSH 驗證機制 - **驗證帳密前** - 連線過程中有一步驟為 client 端比對拿到的 server 公鑰 - 如果連線過, client 就會紀錄,紀錄就可以比對 - 為防止中間人攻擊 :::danger - 僅能防止已登入過的情形 - 初次登入無法避免 > 因為初次連線並未有任何紀錄 ::: - 初次登入會有警告畫面 - ![](https://hackmd.io/_uploads/ByR1RUR-T.png =600x) - ![](https://hackmd.io/_uploads/rkLbA8C-6.png =600x) - 比對發現錯誤會禁止連線 ##### SSH client 公鑰紀錄檔 - `~/.ssh/known_hosts` - ![](https://hackmd.io/_uploads/S1BEhWZzp.png) - 初次連線會記錄到這個檔案中 - 如果不是初次連線會從這裡比對 :::success ## 更換 ssh-server 公鑰 - 為了讓大家得知什麼樣的情況會跳出警告 - 先關閉 ssh 服務 > 做任何相關設定檔調整前建議關閉服務再進行調整 - `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 "[ip address]"` - ![](https://hackmd.io/_uploads/H1wxODRbp.png =500x) - 或是手動刪除也可以 - 根據警告提示行數刪掉 - Tips: 有時 SSH 升級時也會發現公鑰被替換的警告畫面,很可能是因為發現加密的密鑰存在漏洞,所以進行替換 > 手動刪除不會紀錄在 `known_host.old` 中 > [Remove_REF](https://blog.miniasp.com/post/2010/08/30/Ubuntu-Debian-Linux-Regenerate-OpenSSH-Host-Keys) ::: :::info ## Appendix - 中間人攻擊 MITM - Man-in-the-middle attack - 常發生在網路環境不安全的狀態 - 不安全的公共 wifi - ssh 問題:C (Client) 與 S (Server) 連線,其中 A (Attacker) 攻擊者已經藏在不安全的網路環境中 - **client 端** - C 發送請求給 S ,但中途被 A 攔截 - C 與 A 交換公鑰 - A 假裝成 S 接收登入資訊、監控訊息或假傳聖旨 > 詐騙集團攔截到你的帳密資訊 > 想像成詐騙集團偽裝成親友,且詐騙集團有你的帳密,向你索取簡訊驗證碼且說明是為了驗證登入但打成你的電話號碼。 - **server 端** - A 向 S 發送登入請求 - S 收到後交換公鑰 - A 利用剛剛擷取到的登入資訊向 S 進行登入 - 對 S 進行攻擊 > 詐騙集團成功騙到驗證碼,他就可以登入你的系統去盜買商品 - ![](https://hackmd.io/_uploads/ryAoUN3G6.png =500x) > [img_src](https://summer-inequality.blogspot.com/2019/07/linuxssh.html) ::: #### 免密登入操作 - **免密登入 / 憑證登入** - 優點:更安全、更方便 - 無需輸入密碼,就像指紋辨識或臉部辨識不需輸入密碼即可登入。 - 將 client 的公鑰放置於 server 中 - ![](https://hackmd.io/_uploads/H1P9O-1Ma.png =500x) :::success ## 免密登入 ### 產生公私鑰 - `ssh-keygen` - 建議產生公私鑰時可以亂敲鍵盤、亂動滑鼠,增加 entropy,因為在產生亂數時會參考鍵盤與滑鼠的動作,所以動滑鼠可以使亂數越亂 - 預設使用 rsa 加密協議 - 可更換成 `ed25519` 加密,安全性較高,但舊版本伺服器無法使用。 - `-t` 選擇加密協議(無輸入則使用預設), `-b` 可選擇密碼長度 (bits) - `ssh-keygen -t rsa` - `rsa` 預設 - 相容性最好,支援稍舊的版本 - 密碼長度可選擇 `1,024` ~ `16,384` bits ,預設為 `2048` bits - `2048` bits 已足夠安全,但如需提升安全性可選擇更長的 key ,如:`3,072` 或 `4,096` bits - `ed25519` 較推薦使用 - 較新,相容性差,版本支援少 - 安全性最好 - 長度固定,無法改變 - `ecdsa` - 有 `256`, `384`, `521` bits 三種 key 長度可以選擇,無法選擇其他的使用 - 長度相比 RSA 較小 - 理論上較複雜難理解,實作困難 > [REF_Crypto1](https://ithelp.ithome.com.tw/articles/10251031) > [REF_Crypto2](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) - ![](https://hackmd.io/_uploads/SJVEsZyMp.png =500x) - 會詢問使用者路徑與 passphase - passphase 認證,可想像成再多成一層密碼的概念 - Fingerprint / randomart - 舊版本只有 Fingerprint 供大家可以連線時核對,但要檢查一長串文字不太容易 - 新版本更新成隨機圖像樣式,讓大家在連線時核對更方便 - 如何核對? - `ssh -o VisualHostKey=yes [usr_name]@[ip_address]` > [REF](https://blog.gtwang.org/tips/ssh-keygen-randomart/) - 產生密鑰預設路徑 `~/.ssh` - `id_rsa` 私鑰 - `id_rsa.pub` 公鑰 - ![](https://hackmd.io/_uploads/BJrenbkGT.png =500x) - **請注意**公私鑰權限問題 - `.ssh/`資料夾擁有者可讀可寫可執行 - 公鑰的權限:擁有者可讀可寫、其他人與群組使用者可讀 - 其餘檔案:擁有者可讀可寫 > 抽點 sticky bit 跟 chmod ### 複製公鑰 - 方法一 - 使用虛擬機直接複製過去 - `~/.ssh/authorized_keys` 複製到此處(如果沒這個資料夾跟檔案請自行創建) - 方法二 - `ssh-copy-id -i ~/.ssh/id_rsa.pub <usr>@ip` - 方法三 - ssh 遠端登入後複製 ::: #### ssh 相關設定檔案 - 設定檔中 `#` 為註解,且註解後通常為藍字 - 註解的內容為預設內容 - ssh 相關設定檔案 `/etc/ssh/` ##### Client - `/etc/ssh/ssh_config` - ![](https://hackmd.io/_uploads/S1oowgbMp.png =500x) `FIXME: proxycommand 去看,不一定要講` - ForwardAgent 驗證代理 - 讓本地 SSH Key 可由遠端 server 轉送 - PasswordAuthentication - 允許 / 不允許 client 使用密碼登入 ssh server - CheckHostIP - 確認已連線過的主機是否有 IP 不同的問題,發現就提醒 - ConnectTimeout - 連線超過指定秒數就斷線 - port - 預設使用 22 port 進行連線 - **針對指定 Server 做此設定** ```conf= Host serverA HostName 192.168.0.1 ConnectTimeout 30 ``` - 可放置在 `/etc/ssh_config` 中,也可以在 `~/.ssh/` 中創建一個檔案 `config` ##### Server - `/etc/ssh/sshd_config` - **基礎設定** - ![](https://hackmd.io/_uploads/SypzHWWGa.png =500x) - port 選擇使用 port 號 (預設 22 ) - AddressFamily 允許使用的 ip 類型 - `inet`: ipv4 - `inet6`: ipv6 - `any`: 預設皆允許 - ListenAddress 允許連入的 ip address - 預設 `0.0.0.0` 為允許所有主機(含本機) - HostKey 存放私鑰位置 - **認證相關** - ![](https://hackmd.io/_uploads/SJoF4WWzp.png =600x) - LoginGraceTime - 連線完成後,允許 client 停留在輸入密碼畫面多久 - PermitRootLogin - 是否允許使用 root 登入(預設為禁止使用密碼登入) - PubkeyAuthentication - 是否允許使用 Public Key 登入 (預設為 yes) - PasswordAuthentication - 是否允許 client 使用密碼登入(預設為 yes) - PermitEmptyPasswords - 是否允許輸入空密碼登入(預設為 no) - **連線狀態維持** - ClientAliveInterval - Server 端每隔幾秒傳送訊息給 Client 端,Client 端收到訊息會回傳以維持連線。 - ClientAliveCountMax - Client 端幾次沒回應,Server 就進行斷線 > 假設 Interval 設定 30,CountMax 設定 20,代表 Client 10 分鐘未回應就會斷線 - **針對單獨 client 設定** - Match User anoncvs - 如果你只想針對某用戶進行特殊設定,可使用這個功能 ```conf= Match User ray PasswordAuthentication no ClientAliveInterval 30 ClientAliveCountMax 20 ``` - 針對 client 端叫 ray 的人給他這樣的設定 :::info ## Appendix - SSH config 設定 - 觀察檔案會有一行 - ![](https://hackmd.io/_uploads/HyZsJfWMT.png =300x) - 在 `/etc/ssh/` 中會發現有一個目錄 `sshd_config.d` - 用來存放使用者想更動的設定,為了防止 sshd_config 被改壞 - ssh 在運作時更改設定很可能會出問題,所以建議是以關閉狀態改變設定或是在這個目錄新增 `.conf` 檔去做設定 > Demo ::: #### Forward Agent - ![](https://hackmd.io/_uploads/B1dy17-G6.png =400x) - 範例狀況:client 端是員工筆電,Server A 與 Server B 為公司 Server - Server A 無法使用金鑰登入 Server B,密碼驗證也被關閉 - Server B 設定不允許任何外部 ip 連入 - Server B 擁有 Client 的公鑰 > 實例: Server A 為網站 Server , Server B 為公司用機 > 網站要做部署,要從 Server B 拿資料,但員工遠端工作在家 - 使用 Agent Forwarding 可解決 - client 端可以使用金鑰登入 Server A 與 Server B,但因為 Server B 不允許外部連入 - client 端登入 Server A 時將 SSH Key 一起轉給 A ,A 就可以利用 client 的 Key 登入 B :::success ## 較進階一點的操作 - Forward Agent > 需要第三台虛擬機 - `echo $SSH_AGENT_PID` - `echo $SSH_AUTH_SOCK` - 以上兩行指令為顯示 SSH Agent 是否有開啟的參數,有顯示東西基本上就是有順利開啟 - `eval $(ssh-agent)` 啟用 Forward Agent - 如果沒有開啟可以執行這段指令 - `ssh-add ~/.ssh/id_rsa` - 將密鑰加入 forwarding 清單 - `ssh-add -L` - 確認是否加入成功 - `ssh -A [usr_name]@[ip address]` - 使用 Forward Agent 連線 - 如果想每次連線自動啟用 - 至 `/etc/ssh/ssh_config` - 後面加入以下設定 ```conf= Host serverA HostName 192.168.0.1 ForwardAgent yes ``` ::: > [REF and img_src](https://blog.gtwang.org/linux/using-ssh-agent-forwarding-to-avoid-being-asked-passphrase/) ## 遠端檔案傳輸 ### FTP #### 簡介 - **F**ile **T**ransfer **P**rotocol - 最古老的檔案傳輸系統 - 資料明文傳輸 - client-server model 主從式架構 - 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 檔** ::: - 完成設定後,重啟 - 重啟後可以先登入本機測試 - ![](https://hackmd.io/_uploads/SJWFSO0fT.png) - 輸入 `anonymous` 表示匿名登入 - 密碼可以選擇不輸入(不過密碼會紀錄) - 紀錄檔 `/var/log/vsftpd.log` - ![](https://hackmd.io/_uploads/BylvOdRGT.png) :::success ## 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](https://www.ltsplus.com/linux/linux-ftp-command) ::: ### SFTP - **S**SH **F**ile **T**ransfer **P**rotocol - 基本上與 FTP 語法一樣,只是 SFTP 是 SSH 的一部分 > 所以 server 端需要 SSH 才能使用 - 利用 SSH 傳輸,所以 port 號與 SSH 一樣使用 22 - 解決 FTP 明文傳輸的問題 - 效率 - FTP > SFTP - 安全性 - FTP < SFTP - 登入 - `sftp [user]@[ip address]` :::success ## SFTP Server 操作 - 照理來說應該已經把 ssh 安裝完成 ### 設定用戶 - ![](https://hackmd.io/_uploads/HywW2_Rza.png =500x) - 先新增一群組 for sftp 用的 - 然後新增使用者,設定他的 group 為你剛剛新增的 - 記得更改密碼 ### 開啟設定 - `/etc/ssh/sshd_config` - ![](https://hackmd.io/_uploads/B19FqOCzT.png =500x) - 找到此行確認註解有沒有拿掉(預設應該就沒有註解) - 最後用 Match 的方式 - ![](https://hackmd.io/_uploads/rkCfkK0MT.png =500x) - ![](https://hackmd.io/_uploads/SybvJtAfp.png =500x) ```conf= Match Group sftp ForceCommand internal-sftp ChrootDirectory /var/sftp/test PasswordAuthentication yes ``` - 重啟服務 - ![](https://hackmd.io/_uploads/r1Ytgt0f6.png =500x) - 登入本機! > [REF](https://www.cybrosys.com/blog/how-to-setup-sftp-server-on-ubuntu-20-04) ::: ### SCP - **S**SH copy - `cp` 在 Linux 是複製 - 而 `scp` 為遠端複製檔案 :::success ## scp 操作 - 用法 - `scp [參數] [source] [destination]` - 從本機上傳至遠端 - `scp [upload_file_pwd] [usr_name]@[ip address]:[path]` - `path` 不輸入則為家目錄 - 從遠端上傳本機 - `scp [usr_name]@[ip address]:[download_file_pwd] [path]` - `-r` recursive ,目錄中所有檔案 <!-- - `FIXME: Q: A 可不可以把 B 的檔案複製給 C` --> ::: > [REF](https://blog.gtwang.org/linux/linux-scp-command-tutorial-examples/) ### Rsync - Rsync 能做到 `cp` 跟 `scp` 的事,但 Rsync 的效率比 `cp` 跟 `scp` 好 - 靈活性高 - 除了複製檔案,也非常適合用來作備份工具 - 可使用於本機與遠端 - 支援連結檔與設備檔 - 複製後保留檔案的擁有者、群組與權限設定 - 在第一次複製檔案時,會複製完整的檔案內容 - 如複製時發現有一樣檔案在裡面,會利用 Delta transfer 演算法**檢查新舊檔案之間的差異,只傳送有變動的部份** - 節省複製的時間,可加快備份速度(大檔案傳輸時會有更明顯的差異) - 進行遠端傳輸時,可節省網路頻寬 - 支援資料的自動壓縮與解壓縮,也可節省網路頻寬 :::success ## rsync 操作 - 為內建工具,但如果沒安裝 - `sudo apt install rsync` ### 基礎語法 - `rsync [參數] [來源檔案] [目的檔案]` > 與 scp 相似 ### 常見參數 | 參數 | 說明 | | ----------------------- |:-------------------------------------------------------------------------------------------------- | | `-v` | verbose 模式,輸出比較詳細的訊息 | | `-r` | 遞迴(recursive)指定所有子目錄下的目錄與檔案。 | | `-a` | 封裝備份模式,遞迴備份所有子目錄下的目錄與檔案,保留連結檔、檔案的擁有者、群組、權限以及時間戳記。 | | `-z` | 啟用壓縮。 | | `-h` | 將數字以比較容易閱讀的格式輸出。 | | `-e` | 遠端連線設定處理 | | `-P` / `--progress` | 顯示傳輸進度 | | `--delete` | 同步將不存在於來源端的檔案刪除 | | `--include` | 只包含特定檔案 Ex.`--include '*.txt'` | | `--exclude` | 排除特定檔案,`--exclude '*.txt'` | | `--remove-source-files` | 自動刪除來源檔案 | | `--existing` | 只更新目的端既有檔案 | ### 常見使用情境 #### 基本本機複製 - `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` 而佔用網路頻寬 - `rsync -avzh --bwlimit=100K wzray@192.168.1.12:/home/wzray/ ~/file` #### 自訂 port 號 - 預設由 SSH port 22 發送 - 如果想更換方式可輸入 `-e` - `rsync -avzh -e 'ssh -p 12345' ~/file wzray@192.168.1.12:/home/wzray/` - 則可以使用 ssh 往 port 12345 發送 #### 同步刪除檔案 - 如果第二次複製時發送端的部分檔案已刪除,想要在目的端同步刪除該檔案 - `rsync -avh --delete /home/wzray/a/ /home/wzray/b/` #### 備份特定檔案 - 可選擇排除特定檔案 - `rsync -avh --exclude '*.txt' myfolder/ backup/` - 可以一次指定排除多種檔案 - `rsync -avh --exclude '*.txt' --exclude '*.py' myfolder/ backup/` - 也可以搭配 include 使用 (請注意語法,先 include 再 exclude) - `rsync -avh --include '*.c' --include '*/' --exclude '*' myfolder/ backup/` - 包括目錄的 c 檔案以及子目錄裡的 c 檔案。 #### 自動刪除來源檔案 - `rsync -avh --remove-source-files myfolder/ backup/` - 就像是剪下貼上 #### 只更新既有檔案 - 只針對已經複製過的檔案 - `rsync -avh --existing myfolder/ backup/` > [REF1](https://blog.gtwang.org/linux/rsync-local-remote-file-synchronization-commands/) > [REF2](https://hackmd.io/@celineyeh/ByHCum98B) ::: :::success ## rsync Server - rsync server 使用 873 port - 開啟 `/etc/rsyncd.conf` - ![](https://hackmd.io/_uploads/ByAdM5RMa.png) ```conf= motd file = /etc/rsyncd.motd log file = /var/log/rsyncd.log pid file = /var/run/rsyncd.pid lock file = /var/run/rsync.lock [test] comment = test path = ~/fileA/ read only = yes ``` - 可至另外一台主機 - ![](https://hackmd.io/_uploads/B1XJH5CGp.png) - ![](https://hackmd.io/_uploads/HkNQrcCzp.png) - 注意多一個斜線與少一個斜線的差別 - 即可用剛剛所學的參數 rsync 下來 - ![](https://hackmd.io/_uploads/Hy8vrqAzp.png) ::: ## 進階延伸 ### 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` - **情境一:** `FIXME: 帶個實際數字舉例` - ![](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 ,完成繞過防火牆限制 - ![](https://hackmd.io/_uploads/HJu_B80MT.png) - `ssh -L 9090:localhost:8080 [username]@[server]` - **Client** - 你的電腦 - **SSH Server** - 防火牆後的 Server - `[username]@[server]` - **Target Server** - 防火牆後的 Server - localhost:8080 > `bind address`沒輸入代表使用預設 `localhost` > 如果要開放對外可以改成 `0.0.0.0` > `host` 的 `localhost` 是只針對 `server` 的 `localhost` - **情境二:** `FIXME: 帶個實際數字舉例` - ![](https://hackmd.io/_uploads/r1R2IUCza.png) - 前面情境為 Server 能連入的情況,那如果今天權限不足以連入要怎麼辦 - 如果防火牆後有一台你的機器且可用 ssh 連入即可完成 - ![](https://hackmd.io/_uploads/S1wRPLAfa.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 代理伺服器,讓你能夠從外面連回內網裡的所有服務 > [REF1](https://www.uuu.com.tw/Public/content/article/17/170320tips.htm) > [img_src and REF2](https://johnliu55.tw/ssh-tunnel.html) ## 課後練習 :::spoiler - 現場有一 FTP Server ,請試著利用匿名的方式取得 File.txt 的檔案,密碼請輸入你的學號 - FTP 練習當作一次簽到 - ip: `10.107.21.201` - 請截圖過程以及內容,並與這週的作業一併繳交 :::