###### 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
- 
> [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 中的一種協議 -->
- 支援的使用者軟體比較多
- 傳輸資料時未加密 (明文傳輸)
- 有心人士擷取封包 => 裸奔的資料 (帳號密碼)
- 沒有驗證機制,無法保證是否為本人發送
> 
- 連線流程:
- 終端使用者(本機)與遠端伺服器建立連線,port 號為 23 號
- 終端使用者進行遠端伺服器帳號密碼登入
- 遠端伺服器回應終端使用者
- 
> [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


-->
## 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)
- 
- 常用的 port 會記錄在 `/etc/service`
> Demo
#### Well-Known Ports
- 0
- 保留 port ,平常不會啟用
- 1 ~ 1023 需**超級使用者權限**才能占用這些 port
> 範圍中的服務都是一些比較古老、對系統重要的服務
<!-- > `FIXME: 一個port可以提供多個process嗎? Nope, 辦不到的原因(要再去聽一次影片)` -->
- 
> [圖片來源](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://www.iana.org/)
:::
### SSH
- 
> [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 - 加密式連線
- 將人看得懂的原始資料,經過演算法進行加密,變成人看不懂的亂碼後進行傳輸,而當接收端收到資訊想查閱時再進行解密。
> 情境例子:我為了不想讓周遭的人聽到我跟朋友的交談內容,我把我講的話翻譯成獨創語言,之後說給聽得懂獨創語言的朋友聽。
### 常見加密方式
> 所以對稱、非對稱各自優缺差別在哪裡
#### 對稱式加密
- 接收端與發送端皆持有相同的密鑰,用來做加解密
- 
> [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):自己保留用
> 簡稱公鑰、私鑰
- 利用其中一隻進行加密,則一定要用另外一隻進行解密
- 公鑰加密私鑰解密
- 私鑰加密公鑰解密
> 兩模式皆可
> 就像兩人持有不同的翻譯機
> 我先拿了中翻英的系統加密,但一定要拿英翻中的系統才能解密
> 但公鑰是拿來傳給別人用的,所以私鑰加密公鑰解密這件事不會拿來加密訊息
> 加密數位簽章
- 
- 首次傳輸,收件方會與寄件方交換公鑰
- 寄件方要發送資料,先利用收件者的公鑰進行加密,而收件方收到加密資料後再用自己的私鑰解密
- 收到資料了!這樣就結束?還有問題存在
- 如果中間人找到收件方的公鑰,則中間人就可以利用該公鑰加密惡意資訊並傳送給收件方,進而讓收件方受到惡意攻擊,無法驗證傳送者。
- **數位簽章**解決
- 對資料進行二次確認
- 寄件者除了要用收件者公鑰加密資料,寄件者使用自己的私鑰對該封加密訊息的 Hash 簽名
> Hash 雜湊函數
> 簡單來說就是加上了寄件者的簽章,而將 Hash 過的訊息當作簽章
- 到收件方除了利用自己的私鑰解密,也要用寄件者的公鑰進行簽章確認
- 就像是針對資料加密後再上一層指紋鎖
- 流程
- 
- 兩個 雜湊數值相同即可證明是寄件人本人傳送
> [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 的身份去連入
- 
> [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 自己的公鑰
- 完成加密連線通道
- 
> [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_*`
- 
> 多種加密方式
:::info
## Appendix - ssh 好多種?
- `apt-cache search [keyword]` 找軟體指令
- 
- 可以觀察到有許多 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]'` 執行單行指令
- 
- `ssh -f [usr]@[ip adress] '[cmd]'` 背景執行指令
- 即送出指令後可在原本的本機做事情
<!-- - 執行多行指令
-  -->
- `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` 退出連線
:::
#### 密碼登入
- 
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 演算法
- 
- 最終 `A^b mod P` 與 `B^a mod P` 結果應相等
- 所以密鑰相同,為對稱式加密
- 不過 A 與 B 挑的隨機數不同,可用來輔助對稱式加密
- 叫做非對稱式演算法
> 算式不用講
- 連完就丟,不重複連
- 外部的人只聽得到兩端所挑的數字,但這些資訊無法讓外人算出 key 是多少
> [img_src](https://hackmd.io/@yanren1996/rk9OUfY1i)
:::
#### SSH 驗證機制
- **驗證帳密前**
- 連線過程中有一步驟為 client 端比對拿到的 server 公鑰
- 如果連線過, client 就會紀錄,紀錄就可以比對
- 為防止中間人攻擊
:::danger
- 僅能防止已登入過的情形
- 初次登入無法避免
> 因為初次連線並未有任何紀錄
:::
- 初次登入會有警告畫面
- 
- 
- 比對發現錯誤會禁止連線
##### SSH client 公鑰紀錄檔
- `~/.ssh/known_hosts`
- 
- 初次連線會記錄到這個檔案中
- 如果不是初次連線會從這裡比對
:::success
## 更換 ssh-server 公鑰
- 為了讓大家得知什麼樣的情況會跳出警告
- 先關閉 ssh 服務
> 做任何相關設定檔調整前建議關閉服務再進行調整
- `sudo rm /etc/ssh/ssh_host*` 刪除
- 
- `sudo dpkg-reconfigure openssh-server` 重新設定
- 
- 再把 ssh 服務開啟
- 試著用連線過的 client 去連線
- 
- 因為公鑰已經被換過,所以比對的時候發現不一樣
- 解決辦法:
- `ssh-keygen -f "~/.ssh/known_hosts" -R "[ip address]"`
- 
- 或是手動刪除也可以
- 根據警告提示行數刪掉
- 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 進行攻擊
> 詐騙集團成功騙到驗證碼,他就可以登入你的系統去盜買商品
- 
> [img_src](https://summer-inequality.blogspot.com/2019/07/linuxssh.html)
:::
#### 免密登入操作
- **免密登入 / 憑證登入**
- 優點:更安全、更方便
- 無需輸入密碼,就像指紋辨識或臉部辨識不需輸入密碼即可登入。
- 將 client 的公鑰放置於 server 中
- 
:::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)
- 
- 會詢問使用者路徑與 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` 公鑰
- 
- **請注意**公私鑰權限問題
- `.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`
- 
`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`
- **基礎設定**
- 
- port 選擇使用 port 號 (預設 22 )
- AddressFamily 允許使用的 ip 類型
- `inet`: ipv4
- `inet6`: ipv6
- `any`: 預設皆允許
- ListenAddress 允許連入的 ip address
- 預設 `0.0.0.0` 為允許所有主機(含本機)
- HostKey 存放私鑰位置
- **認證相關**
- 
- 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 設定
- 觀察檔案會有一行
- 
- 在 `/etc/ssh/` 中會發現有一個目錄 `sshd_config.d`
- 用來存放使用者想更動的設定,為了防止 sshd_config 被改壞
- ssh 在運作時更改設定很可能會出問題,所以建議是以關閉狀態改變設定或是在這個目錄新增 `.conf` 檔去做設定
> Demo
:::
#### Forward Agent
- 
- 範例狀況: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`
- 
- 安裝後確認
- `/etc/vsftpd.conf` 設定檔位置
- 以下介紹匿名模式的設定(不建議大家利用 ftp 傳送重要檔案)
- 
:::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 檔**
:::
- 完成設定後,重啟
- 重啟後可以先登入本機測試
- 
- 輸入 `anonymous` 表示匿名登入
- 密碼可以選擇不輸入(不過密碼會紀錄)
- 紀錄檔 `/var/log/vsftpd.log`
- 
:::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 安裝完成
### 設定用戶
- 
- 先新增一群組 for sftp 用的
- 然後新增使用者,設定他的 group 為你剛剛新增的
- 記得更改密碼
### 開啟設定
- `/etc/ssh/sshd_config`
- 
- 找到此行確認註解有沒有拿掉(預設應該就沒有註解)
- 最後用 Match 的方式
- 
- 
```conf=
Match Group sftp
ForceCommand internal-sftp
ChrootDirectory /var/sftp/test
PasswordAuthentication yes
```
- 重啟服務
- 
- 登入本機!
> [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/`
- 試著修改一個檔案,再敲一次指令後,觀察他處理了什麼檔案
- 
#### 遠端備份
- 本機 => 遠端
- `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`
- 
```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
```
- 可至另外一台主機
- 
- 
- 注意多一個斜線與少一個斜線的差別
- 即可用剛剛所學的參數 rsync 下來
- 
:::
## 進階延伸
### 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: 帶個實際數字舉例`
- 
- 防火牆後有一台 Server ,但防火牆設定不接受 8080 port 連入,不過接受 22 port
- 使用 tunneling 將 client 中的某個 port (圖中範例 port 9090),對他發送的資料經 SSH 通道轉送至 8080 port,等於連上 client 9090 port 就可以連上 Server 8080 port ,完成繞過防火牆限制
- 
- `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: 帶個實際數字舉例`
- 
- 前面情境為 Server 能連入的情況,那如果今天權限不足以連入要怎麼辦
- 如果防火牆後有一台你的機器且可用 ssh 連入即可完成
- 
- `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]`
- **情境一:**
- 
- 你的電腦上完成了一個服務,並架上 8080 port ,但你的電腦沒有對外 ip,僅有內部 ip
- 準備一台有 Internet 的機器當作對外機器,即可使用 Remote Forwarding 完成
- 對外機器開啟一 port 客戶連入 (圖片範例 port 9090)
- 對外機器藉由 SSH 通道將轉送到 port 8080,客戶即可取得服務
- 
- `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`
:::
- **情境二:**
- 
- 與情境一不同,服務另外架在其他機器上
- 一樣也可以使用 Remote Forwarding
- 
- `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]`
- 情境
- 
- 只要有一台位於內網且具有外部 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`
- 請截圖過程以及內容,並與這週的作業一併繳交
:::