NCNU-OpenSource
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Owners
        • Signed-in users
        • Everyone
        Owners Signed-in users Everyone
      • Write
        • Owners
        • Signed-in users
        • Everyone
        Owners Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee
    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Engagement control
    • Transfer ownership
    • Delete this note
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Versions and GitHub Sync Sharing URL Help
Menu
Options
Engagement control Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Owners
  • Owners
  • Signed-in users
  • Everyone
Owners Signed-in users Everyone
Write
Owners
  • Owners
  • Signed-in users
  • Everyone
Owners Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee
  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       owned this note    owned this note      
    Published Linked with GitHub
    Subscribed
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    Subscribe
    # 遠端連線與傳輸 > 維護網路伺服器最簡單的方式不是跑去實體伺服器前面登入,而是透過遠端連線伺服器連線功能來登入主機, 然後再來進行其他有的沒的維護就是了。[name=鳥哥] - 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 用於在客戶端(如網頁瀏覽器)和伺服器之間傳輸超媒體文件,如 HTML 頁面、圖像、影片等。 --- # SSH 網路傳輸協定 - 全名 : **S**ecure **Sh**ell 安全外殼協定 - 解決 telnet 明文傳輸的問題,但不代表使用 SSH 就不會被干擾、竊聽甚至解密 - 使用**非對稱式加密**方式做使用者驗證 :::info ### 不同加密方式 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) + 雙方各有一對公私鑰,互換公鑰後用對方的公鑰加密 + 公鑰 (public key):提供給遠端主機進行資料加密的行為,也就是說,**大家都能取得你的公鑰來將資料加密**的意思; + 私鑰 (private key):遠端主機使用你的公鑰加密的資料,在本地端就能夠使用私鑰來進行解密。由於私鑰是這麼的重要, **因此私鑰是不能夠外流的!只能保護在自己的主機上**。 ![](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 簽名,以達到二次驗證 > FIXME: 多講數位簽章跟加密的東東 ::: :::info ### Hash 雜湊函式 $H(x) = x \mod B$ - 將不定長度訊息的輸入,演算成固定長度雜湊值的輸出[^hash] - 由雜湊值是無法反推出原來的訊息 - 雜湊值必須隨明文改變而改變 ::: [^hash]: [[資料結構] 雜湊 (Hash) - iT 邦幫忙::一起幫忙解決難題,拯救 IT 人的一天](https://ithelp.ithome.com.tw/articles/10208884) - SSH 的驗證方法 1. 基於密碼的安全驗證 - 知道帳號和密碼,就可以登入到遠端主機 2. 基於金鑰的安全驗證 - 使用者將公鑰放在需要存取的伺服器上 - 使用者端提出身份驗證,告訴伺服器:「我要用 **某個公開金鑰** 登入」 - 伺服器檢查這個公鑰是否存在於 `~/.ssh/authorized_keys` - 伺服器隨機產生一段訊息,加密後送給使用者端,並要求使用者端用 **自己的私鑰 (private key)** 來「簽署」這段挑戰 - 若使用者端成功解開質詢,代表使用者端確實擁有私鑰 → 登入成功 --- 假設今天我想要使用 SSH 傳一個訊息給 BT, 我們 ==*"已經互相擁有對方的公鑰"*== 了 ,並且擁有各自的私鑰,此時會有五個步驟: 1. 我用自己的私鑰將訊息簽名。 2. 我用 BT 的公鑰將訊息加密。(此時,被加密的訊息連我自己也無法還原-只有 BT 的私鑰可以!) 3. 我將訊息傳給 BT。 4. BT 將訊息用自己的私鑰解密。 5. BT 用我的公鑰來確認這個訊息是用我的私鑰簽名的。 上面的例子聽起來萬無一失,但是假設今天我與 BT 還沒有交換公鑰,他們就必須要先連線傳送公鑰給對方。如果壞人屁眼在我要把公鑰傳給 BT 時調包,換成屁眼自己的公鑰,這時與 BT 建立「安全連線」的人,就會是屁眼而不是我了,SSH 能夠提供的保護只在確保公鑰的擁有者同時擁有相對應的私鑰,但是不能保證擁有這個公私鑰組合的人是不是壞人。這就是著名的 **「中間人攻擊」(man-in-the-middle-attack)**。 :::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 是密碼學中常用來代表「惡意的攻擊者」虛構角色的人名 - **中間人攻擊** (**M**an-**i**n-**t**he-**M**iddle Attack, 縮寫: **MITM**) - 在密碼學和電腦安全領域中常提到的一個概念 - 指攻擊者與通訊的兩端分別建立獨立的聯絡,並交換其所收到的資料,使通訊的兩端認為他們正在通過一個私密的連接與對方直接對話,但事實上整個對談都被攻擊者完全控制。 ::: :::warning **我用我自己設定好的帳密登入,不就是用同一把密鑰登入,算不算對稱式加密?** ::: --- ## SSH 連線完整流程 ### 登場角色 + Client:你輸入 `ssh user@server` 的電腦 + Server:伺服器,第一次被連線 ### 1. TCP 連線 Client 與 Server 透過 TCP 建立連線(通常在 port 22) ### 2. 協商與版本交換 雙方交換 SSH 協議版本與支援的演算法清單(加密、壓縮、MAC…),例: + Client:`SSH-2.0-OpenSSH_9.7` + Server:`SSH-2.0-OpenSSH_8.2` ### 3. Host Key 驗證 (伺服器身分驗證) + Server 把它的 **主機公鑰 (Host Public Key)** 傳給 Client。 + Client 端檢查: + **第一次連線** → Client 本地 `~/.ssh/known_hosts` 沒有記錄 → 跳出提示: ```bash= The authenticity of host 'server (192.168.x.x)' can't be established. ECDSA key fingerprint is SHA256:xxxx... Are you sure you want to continue connecting (yes/no/[fingerprint])? ``` + 使用者如果選「yes」→ 伺服器的 host key 會被寫入 `~/.ssh/known_hosts`。 + 之後每次連線都會比對 host key,若不同就會警告(避免遭到中間人攻擊 MITM)。 **這一步不是驗證使用者,而是驗證伺服器真的是我們要的那台。** ### 4. Key Exchange (會話金鑰產生) + 雙方透過 **非對稱金鑰演算法 (例:Diffie–Hellman, ECDH, Curve25519)** 進行 **金鑰交換**。 + 雙方獨立算出一個 **共享會話金鑰 (session key)**,不需在網路上傳輸。 + 之後所有流量都用這個 session key 進行 **對稱式加密 (AES, ChaCha20 …)**。 **從這一步開始,所有通訊都在加密通道中進行。** :::warning **加密通道在 OSI 哪個 Layer?** ::: ### 5. 使用者身份驗證 (Authentication) **密碼登入情況** 1. Client 輸入密碼。 2. 密碼經過已建立的 **加密通道** 傳到 Server。 3. Server 驗證密碼是否正確 4. 正確 → 登入成功;錯誤 → 拒絕。 :::info ### client-server model ![Client-server-model.svg](https://upload.wikimedia.org/wikipedia/commons/thumb/c/c9/Client-server-model.svg/1000px-Client-server-model.svg.png?20141205053432) > 圖片來源 [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** 特徵 - 被動的角色(從) - 等待來自使用者端的請求 - 處理請求並傳回結果 ::: :::warning **所以 SSH 到底是對稱還是非對稱加密?** ::: --- ## 基礎操作 ### 安裝 - 更新軟體的最新資訊及列表: `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 Desktop 中已內建,如果沒有要做連入的主機可以不安裝 `openssh-server` > P.S: Windows 10 1809 的 cmd 中也內建了 openssh-client ::: ### 確認 server 狀態 - 查看服務狀態 - `sudo systemctl status ssh` - 查看 ssh 佔用 port - `sudo ss -ltpn` - `-l`: 列出傾聽狀態(listening)的 sockets - `-t`: 只列出 TCP 的 sockets - `-p`: 顯示使用 sockets 的程式資訊 - `-n`: 不要嘗試把 port 號解析成服務名稱 :::success **Q. http & https 分別用哪個 port?** ::: ### 開啟關閉與重啟 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 被作為頂級域名,不得有任何網域註冊此名稱 :::info 大部分情況下你不會特地 `ssh localhost`,因為直接在本機打指令就能做,最常見情況是: 剛安裝或修改過 `OpenSSH Server` 設定時,會用 `ssh 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]` 等待時間如果超過三秒即斷線 ::: --- ## 密碼登入 - 流程圖 - ![](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. 最後雙方再以協商的密鑰,接收登入訊息並開始操作系統 :::success **Lab 登入** 打開你的 terminal,登入 ```bash= ssh [s學號]@moli.lsa.tw ``` 密碼是 `Temp#2025!` ::: --- ## 利用公鑰進行無密碼登入 一般我們登入伺服器可以透過密碼進行登入,但是安全性的程度會比較沒有像 SSH key 那個安全,而且如果使用 SSH key 登入的話可以就不用每次手動輸入密碼,會方便許多,本篇教如何產生 SSH key 並且設定到伺服器上。 ### 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 ,現在預設為 `2,048` bits - `2,048` bits 以下都不建議用,如需提升安全性可選擇更長的 key ,如:`4,096` bits - `ed25519` 較推薦使用 - 較新,OpenSSH 6.5 版本以後就都支援 - 安全性最好 - 更快的產生金鑰 - 更快的身分驗證 - 長度固定 - 公鑰 `256` bits,被 OpenSSH 編碼成 `68` 個 16 進位字元(chars) - 是使用 SHA-512(SHA-2)和 Curve25519 的 EdDSA 簽名方式 - 扭曲的愛德華茲曲線 - `ecdsa` - 有 `256`, `384`, `521` bits 三種 key 長度可以選擇,無法選擇其他的使用 - 公鑰長度相比 RSA 較小 - 應用了**橢圓曲線加密法** :::warning **鑰匙長度越長 → 一定比較安全?** - RSA - 安全性建立在「大整數分解困難」上。 - 攻擊者必須把一個由兩個大質數乘起來的數拆解回去,這在數學上困難,但隨著硬體與演算法進步(像是 Number Field Sieve, NFS),RSA 的安全性會慢慢下降。 - 因此要維持安全,只能一直「加大鑰匙長度」。 - 今天常見的 **RSA-2048**,大約相當於 **112-bit 對稱金鑰強度**。 - Ed25519 (Elliptic Curve Digital Signature, Edwards Curve 25519) - 安全性建立在「橢圓曲線離散對數問題 (Elliptic Curve Discrete Logarithm Problem, ECDLP)」的困難度上。 - 相較於整數分解,這個問題目前沒有像 NFS 那樣高效的解法。 - 因此 **短很多的鑰匙長度就能達到相同甚至更高的安全強度**。 - Ed25519 的 256-bit 鑰匙安全等級大約等同於 **128-bit 對稱金鑰強度**。 如果要在 RSA 達到類似安全強度,得用到 **RSA-3072 (≈128-bit 強度)** 或 **RSA-4096 (≈152-bit 強度)**。 ::: ### 2. 把公鑰複製到遠端主機 server 上 - 方法一 - 用 ssh-copy-id 傳送公鑰到遠端主機 `ssh-copy-id -i ~/.ssh/id_ed25519.pub [username]@[hostname]` - 若要指定 port `ssh-copy-id -i ~/.ssh/id_ed25519.pub -p [port] [username]@[hostname]` * 方法二,手動複製 1. `cat ~/.ssh/id_ed25519.pub` 2. 用帳號密碼登入遠端主機 server 3. `cd ~/.ssh` 4. 在遠端主機新增檔案 `touch authorized_keys` 5. 將 `id_ed25519.pub` 公鑰內容放入 `authorized_keys`中,以換行方式區分不同支公鑰 `vim authorized_keys` 5. `chmod -R go= ~/.ssh` 把這個資料夾中所有檔案的 group 及 other 權限拿掉 ### 3. 測試是否成功 試試看是否能正常登入使用key登入 ``` $ ssh username@remote_host ``` 如果能夠不需要輸入密碼 就表示已經成功了 :::success **Lab 把金鑰放到剛剛登入的 server** ::: :::info 若遇到權限問題,用 `chmod 600 ~/.ssh/authorized_keys` ::: :::info ### 更換 ssh-server 公鑰 - 為了讓大家得知什麼樣的情況會跳出警告 - 先關閉 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` 中 ::: --- ## Forward Agent :::info **SSH Agent 是什麼?** 它是一個專門管理你的 **私鑰**,以及幫你作 **數位簽章** 的程式 在 SSH 中,**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 的公鑰== - 實例: Server A 為網站 Server , Server B 為公司用機 &gt; 網站要做部署,要從 Server B 拿資料,但員工 Work from home - 使用 Agent Forwarding 可解決,透過 client 端登入 Server A 時將 SSH Key 一起轉給 A ,A 就可以利用 client 的 Key 登入 B 流程: 1. client 在本地有 `ssh-agent`,裡面已經有私鑰。 2. client 連上 `ssh ServerA -A`(`-A` 開啟 agent forwarding)。 3. ServerA 上的 `ssh` 如果要再連 ServerB,它會把簽名請求透過 SSH 通道回傳到 client 的 agent。 4. client agent 幫忙完成簽章,再回傳結果。 關鍵點: - 私鑰 **永遠不會離開本地電腦**。 - 遠端機器只能透過 SSH 通道「借用」你的 agent 做簽章。 :::danger **舉一反三** - 如果你登入的遠端主機 (hostA) 已被入侵,攻擊者可能利用你的 agent 代理去登入其他機器 (hostB)。 - 雖然私鑰不會洩漏,但只要 agent session 還活著,他們就能「借用」你的身分。 - 僅在信任的主機上使用 `-A`。 更安全的替代方案是 ProxyJump / ProxyCommand 或 ssh certificates。 ::: --- ## 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 操作 - `ftp [ip address]` 登入 - 如果是公眾的 server,username 可輸入`anonymous`作為匿名,密碼可空白 - `put [client_file] [server_file] ` 上傳檔案,如 server 上已有重複的檔案則覆蓋 - `get [server_file] [client_file]` 下載檔案,如 client 上已有重複的檔案則覆蓋 - `ls` 與 Linux 指令一樣, list - `cd` 與 Linux 指令一樣, change directory - `lpwd` 顯示本機端目前位置 - `lcd` 切換本機端位置 - `help` 查看更多指令 - `bye` 退出 --- ## 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]` :::success **實做** 在你本機捏一個 `學號.abc` 用 ftp or sftp 丟到 moli.lsa.tw `/var/class1001/` 裡頭 ::: ## SCP - **S**SH copy <!-- 不一定是 SSH backend? --> - `cp` 在 Linux 是複製 - 而 `scp` 為遠端複製檔案 ### scp 操作 - 用法 - `scp [參數] [source] [destination]` - 從本機上傳至遠端 - `scp [本機檔案路徑] [usr_name]@[hostname]:[遠端檔案路徑]` - `path` 不輸入則為家目錄 - 從遠端下載到本機 - `scp [usr_name]@[hostname]:[遠端檔案路徑] [本機檔案路徑]` - `-r`: recursive ,目錄中所有檔案 - `scp [folder]/** [destination]` --- ## Rsync - Rsync 能做到 `cp` 跟 `scp` 的事,但 Rsync 的效率比 `cp` 跟 `scp` 好 - 靈活性高 - 除了複製檔案,也非常適合用來作備份工具 - 可使用於本機與遠端 - 支援連結檔與設備檔 - 支援複製後保留檔案的屬性(擁有者、群組與權限設定) - 在第一次複製檔案時,會複製完整的檔案內容 - 如複製時發現有一樣檔案在裡面,會利用 delta-transfer 演算法**檢查新舊檔案之間的差異,只傳送有變動的部份** - 節省複製的時間,可加快備份速度(大檔案傳輸時會有更明顯的差異) - 進行遠端傳輸時,可節省網路頻寬 - 支援資料的自動壓縮與解壓縮,也可節省網路頻寬 ### rsync 操作 - 為內建工具,但如果沒安裝 - `sudo apt install rsync` ### 基礎語法 - `rsync [參數] [來源檔案] [目的檔案]` ### 常見參數 | 參數 | 說明 | | ----------------------- |:-------------------------------------------------------------------------------------------------- | | `-v` | verbose 模式,輸出比較詳細的訊息 | | | `-a` | 封裝備份模式,遞迴備份所有子目錄下的目錄與檔案,保留連結檔、檔案的擁有者、群組、權限以及時間戳記。 | | `-z` | 啟用壓縮。 | | `-h` | 將數字以比較容易閱讀的格式輸出。 | | | `-P` / `--progress` | 顯示傳輸進度 | | `--delete` | 同步將不存在於來源端的檔案刪除 | :::spoiler > FIXME: 指令測試 > - rsync -az:什麼都不顯示 > ![image](https://hackmd.io/_uploads/BJrxXVl2lx.png) > - rsync -avz -P > ![image](https://hackmd.io/_uploads/HySqXEx3ex.png) > - rsync -az -P > ![image](https://hackmd.io/_uploads/ryIAXNl2ex.png) > - rsync -avz --info=progress2:背景模式跑 rsync,且會有進度條 > ![image](https://hackmd.io/_uploads/Sk0XxEe3ge.png) ::: ### 常見使用情境 ### 基本本機複製 - `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/` --- :::spoiler > FIXME: BT 小筆記 - 不透過 ssh 的方式把遠端的資料 mirror 回來 - 沒有經過 ssl 加密 -> 密碼用明文 - read only: no -> 讓使用者可以寫入資料 步驟紀錄 ![image](https://hackmd.io/_uploads/Sys2Rmxnll.png) ![image](https://hackmd.io/_uploads/Sy-C07xhlg.png) ![image](https://hackmd.io/_uploads/rJMkkVe3xl.png) ![image](https://hackmd.io/_uploads/SyVg1Elhle.png) ![image](https://hackmd.io/_uploads/Byeby4xhll.png) ![image](https://hackmd.io/_uploads/BJa-kNe2el.png) ![image](https://hackmd.io/_uploads/r1bz1Eghge.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` - **情境一:** - ![](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]` :::success **Lab 作業!** ![圖片](https://hackmd.io/_uploads/BkOMc_jhlx.png) 我們在 moli.lsa.tw port 8080 開了一個簽到網站,請你用上 ssh tunnel 所學,想辦法進到這個網站完成簽到並截圖,網站的 url 也要截進去! 簽到的紀錄會放在 `/opt/signin-app/signlog.csv`,請你用上遠端檔案傳輸方式,把這個簽到紀錄下載到自己的虛擬機裡,截圖裡面的內容 ::: - **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/rJSrtDG2xe.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` ::: - **情境二:** - 有一個在內網裡的內部服務,你的電腦可以用 IP `192.168.1.100` 和 Port 8080 連到這個服務,但因為都在內網所以大家都沒有 Internet IP,所以無法讓你從家裡透過 Internet 連回來: - ![](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 一般的 Port Forwarding 只能夠轉送一個 IP 上的一個 Port ,當你有很多 IP 或很多 Port 想轉時就只能一個一個開,很不方便 - 語法 - `ssh -D [bind_address:][port] [username]@[SSH Server]` - 情境 - ![dynamic](https://hackmd.io/_uploads/HJx-Cvz2lx.png) - 只要有一台位於內網且具有外部 IP 的機器,你就可以利用這個方法建立一個 SOCKS 代理伺服器,讓你能夠從外面連回內網裡的所有服務 > FIXME: 三種 tunnel 模式想個 demo > FIXME: 線要畫確實,包括從哪進、從哪出,下面幾張圖亦然 > FIXME: 記得留時間,後面 tunnal 部分需要緩衝 --- # 作業 登入 lsa server,在 /var/exercise/ 裡有多個檔案,這些檔案裡頭除了有幾百行亂碼,裡面還參雜你們的學號,你們必須找到所有出現你學號的檔案 # 補充資料 - [如何讓兩台虛擬機可以用 ssh 連線 - HackMD](https://hackmd.io/@oJ7l_4AbTkCmGKJnAmApWw/ryXtBNePF) - [遠端連線虛擬機 - HackMD](https://hackmd.io/@wzray07/Bkhh64xGT)

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password

    or

    By clicking below, you agree to our terms of service.

    Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully