掌握SSH這篇就夠了

SSH 是每一臺電腦的標準配置,Linux 就不必說了,連 windows 也從 2018 年開始自帶 OpenSSH 了。
它主要的用途是登陸到遠程電腦中執行命令,在云開發的時代,它是每個程序每天都要用到的工具。本文將簡單介紹一下它的原理,
基本用法以及端口轉發和動態轉發等高階用法。

介紹

SSH 叫安全外殼協議(Secure Shell),是一種加密的網絡傳輸協議,可在不安全的網絡中網絡服務提供安全的傳輸環境。它通過在網絡中創建安全隧道來實現 SSH 客戶端和服務器之間的連接。最早的時候,互聯網通信都是明文通信,一旦被截獲,內容就會被暴露。1995年,芬蘭學者 Tatu Ylonen 設計了 SSH 協議,將登錄信息全部加密,成為互聯網安全的一個基本解決方案,迅速在全世界獲得推廣,目前已經成為所有操作系統的標準配置。

SSH 是一種協議, 存在多種實現,既有商業實現,也有開源實現(OSSH,OpenSSH)。本文使用的自有軟件 OpenSSH, 畢竟它是目前最流行的 SSH 實現,而且是所有操作系統的默認組件。

TIPS: OpenSSH發展史
1995 年 7 月, Tatu Ylonen 以免費軟件的形式將一套保護信息傳輸的程序(也就是 SSH )發布出去。程序很快流行,到年底已經有兩萬用戶,遍布五十國家。所以在年底時,他創立了 SSH 通信安全公司來繼續開發和銷售 SSH, 所以它變成了專有軟件。在 1999 年,瑞典程序員基于 SSH 最后一個開源的版本 1.2.12 開發了 OSSH,之后 OpenBSD 開發者在 OSSH 的基礎上進行大量修改,形成了 OpenSSH。它是目前唯一一種最流行的 SSH 實現,成為了所有操作系統的默認組件。

原理介紹

SSH 之所以一經提出,就得到了快速發展,是因為數據的安全性對任何人都非常重要。這里我們對其保護數據安全的原理進行探究。

在聊加密前先介紹一下幾個密碼學的基本概念:

  • 明文plaintext 指傳送方(一般指客戶端)想要接受方(一般指服務端)獲得的可讀信息
  • 密文ciphertext 指明文經過加密后所產生的信息
  • 秘鑰key 指用來完成加密、解密、完整性驗證等密碼學應用的密碼信息,是明文轉換為密文或密文轉換為明文的算法需要的參數
  • 私鑰 指私有的秘鑰
  • 公鑰 指公開的秘鑰

對稱加密

對稱加密就是加密或解密使用的是同一個秘鑰。比較常用的對稱加密算法有 AES,DES等。其具體的時序圖如下:


ssh_symmetric.png

對稱加密的優點是加解密效率高,速度快。對于服務端而言,它和每個客戶端都要有一個秘鑰,龐大的客戶端數目導致秘鑰數目多,而且一旦機器被登錄,所有的秘鑰都泄露,所以缺點是秘鑰的管理和分發比較困難,不安全。

非對稱加密

非對稱加密需要一對秘鑰來進行加密和解密,公開的秘鑰叫公鑰,私有的秘鑰叫私鑰。注意公鑰加密的信息只有私鑰才能解開(加密過程),私鑰加密的信息只有公鑰才能解開(驗簽過程)。比較常用的非對稱加密算法有 RSA。其具體的時序圖如下:

ssh_asymmetric.png

非對稱加密的優點是安全性更高,秘鑰管理比較方便,每個服務器只要維護一對公私鑰即可。缺點是加解密耗時長,速度慢。不過對于現在的計算機而言,這點成本可以忽略不計。

中間人攻擊

中間人攻擊的英文全稱是 Man-in-the-middle attack,縮寫為 MITM。在密碼學和計算機安全領域中是指攻擊者與通訊的兩端分別創建獨立的聯系,并交換其所收到的數據,使通訊的兩端認為他們正在通過一個私密的連接與對方直接對話,但事實上整個會話都被攻擊者完全控制。在中間人攻擊中,攻擊者可以攔截通訊雙方的通話并插入新的內容。在許多情況下這是很簡單的(例如,在一個未加密的 Wi-Fi 無線接入點的接受范圍內的中間人攻擊者,可以將自己作為一個中間人插入這個網絡)。其具體的時序圖如下:


ssh_mitm.png

受到中間人攻擊的關鍵原因是客戶端不知道服務端的公鑰真假,服務端也不知道客戶端的公鑰真假。所以破解這個問題的關鍵是如何相互認證,也就是要像黃宏《開鎖》小品里一樣證明我就是我,你就是你。

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@  WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!   @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that a host key has just been changed.
The fingerprint for the ECDSA key sent by the remote host is
SHA256:sYNNR1L6T5cSAG4BndqtdDhJEI0eB9LamBTkuIue3+0.
Please contact your system administrator.
Add correct host key in /Users/xx/.ssh/known_hosts to get rid of this message.
Offending ECDSA key in /Users/xx/.ssh/known_hosts:40
ECDSA host key for [xx.com] has changed and you have requested strict checking.
Host key verification failed.

基本用法

生成公鑰

ssh-keygen 是安全外殼( SSH )協議套件的標準組件,用于生成,管理和轉換身份驗證密鑰。

參數說明

  • -b bits 指定要創建的秘鑰中的位數,默認 2048 位。值越大,密碼越復雜
  • -C comment 注釋,在 id_rsa.pub 中末尾
  • -t rsa/dsa等 指定要創建的秘鑰類型,默認為 RSA
  • -f filename 指定公私鑰的名稱,會在 $HOME/.ssh 目錄下生產私鑰 filename 和公鑰 filename.pub
  • -N password 指定使用秘鑰的密碼,使得多人使用同一臺機器時更安全

常用命令

# 生成公私鑰,默認文件為 ~/.ssh/id_rsa
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"

管理秘鑰

ssh-agent 和 ssh-add 是安全外殼(SSH)協議套件的標準組件,用于管理私鑰。一般情況下我們使用不帶密碼的 id_rsa 作為我們的默認私鑰,此時是沒必要啟動 ssh-agent 的。當我們碰到以下兩種情況則需要它:

  1. 使用不同的秘鑰連接到不同的主機時,需要手動指定對應的秘鑰。(ssh-agent 幫我們選擇對應的秘鑰進行認證)
  2. 當私鑰設置了密碼,而我們又需要頻繁的使用私鑰進行認證。(ssh-agent 幫我們免去重復輸入密碼)

代理常用命令

# 啟動代理
eval `ssh-agent`
# 關閉代理
ssh-agent -k
# 在 ~/.bashrc 中加入以下來實現登陸自動啟動 ssh-agent,退出自動 kill 掉程序
eval $(ssh-agent -s) > /dev/null
trap 'test -n "$SSH_AGENT_PID" && eval `/usr/bin/ssh-agent -k` > /dev/null' 0

# 查看代理中的私鑰
ssh-add -l
# 查看代理中私鑰對應的公鑰
ssh-add -L
# 移除指定的私鑰
ssh-add -d /path/of/key/key_name
# 移除所有的私鑰
ssh-add -D

發送公鑰

ssh-copy-id 是一個用來將公鑰放到服務器上的腳本。它通過 SSH 密碼登陸遠程服務器,并將指定的公鑰放到遠程服務器 $HOME/.ssh/authorized_keys 中。這個操作也可以先登陸到服務器中,然后通過 vi 等文本編輯命令向 $HOME/.ssh/authorized_keys 中加入允許登陸的公鑰。不過對于云服務器可以在啟動服務器時在頁面上操作綁定公鑰,這樣更安全些(阿里云和騰訊云默認關閉秘鑰登陸 PasswordAuthentication no )。特別注意的是,千萬別在公共的網絡中通過密碼登陸遠程服務器,而秘鑰登陸沒有問題。

# 發送公鑰的兩種方式(等價)
ssh-copy-id -i ~/.ssh/id_rsa.pub user@host
ssh user@host 'mkdir -p .ssh && cat >> .ssh/authorized_keys' < ~/.ssh/id_rsa.pub

登錄

登錄配置

SSH 登陸服務器需要知道服務器的主機地址(主機名或主機 IP 地址),用戶名和密碼,有時還要指定端口號(默認 22 )。主機名還好,但是主機IP 地址就比較難記的,特別是當你可能要登錄十幾臺服務器時。一般我們使用的登陸命令如下:

# 登陸目標服務器( 172.17.132.120 )
ssh -p 58422 user@172.17.132.120
# 通過跳板機登陸目標服務器( 172.17.132.120 )
ssh -p 58422 user@jumper.example.com ssh user@172.17.132.120
# 端口映射
ssh -p 58422 user@jumper.example.com -fNL 5433:172.17.132.120:5432 -N

通過配置 $HOME/.ssh/config 可以使用以下命令來登錄。

# 登陸目標服務器( 172.17.132.120 )
ssh target
# 通過跳板機登陸目標服務器( 172.17.132.120 )
ssh jump_target
# 端口映射
## 登陸時通過 LocalForward 配置
ssh jump_target
## 使用-L來實現本地端口映射
ssh -C -N -g -L 5433:127.0.0.1:5432 jump_target
# 通用配置,所有配置都使用
Host *
    AddKeysToAgent yes      # 將私鑰添加到ssh-agent中
    UseKeychain yes         # 保存密碼到agent中
    ServerAliveInterval 10  # 連接心跳間隔10s
    ServerAliveCountMax 3   # 重連次數為3
# target配置
Host target
    HostName 172.17.132.120
    User user
    Port 58422
    IdentityFile ~/.ssh/id_rsa
# 跳板機配置
Host jumper
    HostName jumper.example.com
    User user
    Port 58422
    IdentityFile ~/.ssh/id_rsa
Host jump_target
    HostName 172.17.132.120
    User user
    Port 22
    IdentityFile ~/.ssh/id_rsa
    ProxyCommand ssh user@jumper -W %h:%p 2>/dev/null
    LocalForward 5433 localhost:5432    # 本地5433映射到jump_target的5432

TIPS:
VS Code 的 Remote 插件會讀取本地的配置文件 $HOME/.ssh/config,以便像本地一樣進行遠程開發。

首次登陸

一般在 $HOME/.ssh 目錄下除了公私鑰文件,config 配置文件,authorized_keys 認證文件外,還有一個 known_hosts 文件。
這個文件記錄了遠程主機 ip 和遠程主機對應的公鑰指紋。我們在第一次登陸(密碼或秘鑰登陸)服務器時,會有如下的提示界面:

### SSH 首次登陸的提示
The authenticity of host '127.0.0.1 (127.0.0.1)' can't be established.
ECDSA key fingerprint is SHA256:HosOqhcUmbB7QG81yCuDPkvxTgot+vpple+czXPrEug.
ECDSA key fingerprint is MD5:fd:d7:e1:2c:42:4e:b4:2d:a3:21:4d:d1:c4:74:64:2d.
Are you sure you want to continue connecting (yes/no)?

此時 known_hosts 并沒有 127.0.0.1 這臺機器的指紋信息,所以顯示這個提示來讓我們確認這個指紋是否是目標機器的 ECDSA 算法的指紋。
當我們輸入 yes 確認后,在下次登錄的時候,遠程主機發送過來的公鑰指紋,直接和 known_hosts 文件中對應 ip 的公鑰指紋比較即可。

# 本機查看服務器 172.17.132.120 的所有公鑰(要與服務器上 /etc/ssh 下面的公鑰 *.pub 一致)
ssh-keyscan -p 22 172.17.132.120

# 查看服務器公鑰 ecdsa 的指紋 -E md5/sha256 指紋 hash 算法
ssh-keygen -E md5 -lf /etc/ssh/ssh_host_ecdsa_key.pub
## 256 MD5:84:3d:9c:6e:75:f2:6b:b2:0b:40:aa:d6:29:2f:b4:40 no comment (ECDSA)
## 256 SHA256:ZoGnph63gnKLC9wQYrHYVU8ROTf6+K9LKAjn+jrXB2o no comment (ECDSA)

# 從客戶端查看服務器公鑰 ecdsa 的指紋(初次登陸時要驗證的指紋)
ssh-keyscan -t ecdsa -p 22 172.17.132.120 |ssh-keygen -lf -

# 公鑰轉換成特定指紋 hash 算法的指紋
awk '{print $2}' /etc/ssh/ssh_host_ecdsa_key.pub | base64 -d|openssl sha256 -binary |base64

TIPS: known_hosts的重要性
known_hosts 這個文件是客戶端驗證服務端身份的重要依據。每次客戶端向服務端發起連接請求時,不僅服務端要驗證客戶端的合法性,客戶端也需要驗證服務端的身份。客戶端就是通過 known_hosts 中的公鑰指紋來驗證服務器是否發生了變化。它在一定程度上能避免中間人攻擊,除了第一次登陸,因為那時 known_hosts 中還沒有服務器的身份信息,所以對于首次提示的登陸指紋信息還是需要和服務器比對的。最安全保險的做法是第一次登陸就使用秘鑰登陸。

登陸流程

  1. 版本號協商階段
  2. 密鑰和算法協商階段
    服務端和客戶端分別發送算法協商報文給對方,報文中包含自己支持的公鑰算法列表、加密算法列表、消息驗證碼算法列表、壓縮算法列表等。服務端和客戶端根據對方和自己支持的算法得出最終使用的算法。服務端和客戶端利用 DH 交換算法、主機密鑰對等參數,生成會話密鑰和會話 ID。
  3. 認證階段( publickey > gssapi-keyex > gssapi-with-mic > password )
  4. 會話請求階段
  5. 會話交互階段

密碼登陸

密碼登陸的認證流程如下:

  1. 客戶端使用密鑰和算法協商階段生成的會話密鑰加密賬號、認證方法、口令,將結果發送給服務器。
  2. 服務端使用獲得的會話密鑰解密報文,得到賬號和口令。
  3. 服務端對這個賬號和口令進行判斷,如果失敗,向客戶端發送認證失敗報文,其中包含了可以再次認證的方法列表。
  4. 客戶端從認證方法列表中選擇一種方法進行再次認證。
  5. 這個過程反復進行,直到認證成功或者認證次數達到上限,服務端關閉本次TCP連接。
ssh_password

秘鑰登陸

秘鑰登陸的認證流程如下:

  1. 客戶端使用密鑰和算法協商階段生成的會話密鑰加密賬號、認證方法、id_rsa.pub,將結果發送給服務端。
  2. 服務端使用會話密鑰解密報文,得到賬號、id_rsa.pub。服務端在 $HOME/.ssh/authorized_keys 中找對應的公鑰,如果沒有找到,發送失敗消息給客戶端,如果找到,比較客戶發送過來的這個公鑰和找到的公鑰,如果內容相同,服務端生成一個隨機的字符串,簡稱“質詢”,然后使用找到的公鑰加密這個質詢,然后使用會話密鑰再次加密。
  3. 服務端把這個雙重加密的數據發送給客戶端
  4. 客戶端使用會話密鑰解密報文,然后使用 id_rsa 再次解密數據,得到質詢。
  5. 客戶端使用會話密鑰加密質詢,發送給服務端。
  6. 服務端使用會話密鑰解密報文,得到質詢,判斷是不是自己生成的那個質詢,如果不相同,發送失敗消息給客戶端,如果相同,認證通過。
ssh_key

二者區別

我們常說使用秘鑰登陸比密碼登陸更方便更安全,為什么這么說呢?方便是因為不用記密碼,安全是一方面敏感關鍵的密碼沒有在傳輸,另一方面是因為質詢的存在使得在一次對話中同時驗證了客戶端和服務端。

高階用法

免密安全傳輸

scp/rsync/sftp 都可以基于 SSH 來進行免密安全傳輸,常見命令如下:

# 從本地同步 src.tar.gz 文件到遠程服務器 jump_target 的目錄 /path/to/des/
scp src.tar.gz jump_target:/path/to/des/
rsync -avz src.tar.gz jump_target:/path/to/des/

# 從遠程服務器 jump_target 的文件 /path/to/src.tar.gz 到本地
scp jump_target:/path/to/src.tar.gz .
rsync -avz jump_target:/path/to/src.tar.gz .

端口轉發

SSH 不僅僅能夠自動加密和解密 SSH 客戶端與服務端之間的網絡數據,同時,SSH 還能夠提供了一個非常有用的功能,那就是端口轉發,即將 TCP 端口的網絡數據,轉發到指定的主機某個端口上,在轉發的同時會對數據進行相應的加密及解密。如果工作環境中的防火墻限制了一些網絡端口的使用,但是允許 SSH 的連接,那么也是能夠通過使用 SSH 轉發后的端口進行通信。轉發主要分為本地轉發與遠程轉發兩種類型。

轉發常用參數

  • -C: 壓縮傳輸,提高傳輸速度。
  • -f: 將 SSH 傳輸轉入后臺執行,不占用當前 SHELL, 常與 -N 一起使用
  • -N: 建立靜默連接(建立了連接但看不到具體會話)
  • -g: 在 -L/-R/-D 參數中,允許遠程主機連接到建立的轉發的端口,如果不加這個參數,只允許本地主機建立連接。
  • -L: 本地端口轉發
  • -R: 遠程端口轉發
  • -D:動態轉發( SOCKS 代理)
  • -P: 指定 SSH 端口

本地端口轉發

由本地網絡服務器的端口 A,轉發到遠程服務器端口 B。說白了就是,將發送到本地端口 A 的請求,轉發到目標端口 B。格式如下

ssh -L 本地網卡地址:本地端口:目標地址:目標端口 用戶@目標地址
常見的應用場景見下圖:

ssh_local

對應的命令如下:

# jump_target 服務器上的 3306 端口服務映射到本地 33306 `mysql -u root -p root -H localhost -P 33306`
## 1 是 2,3,5 路線中的加密通道,將本地 33306 的網絡數據轉發到 jump_target 的 3306 端口
ssh -C -N -g -L 33306:localhost:3306 jump_target
## 在 2,3 中搞了個加密通道,然后在跳板機上將本地 33306 的網絡數據轉發到 172.17.132.120 的 3306 端口
ssh -C -N -g -L 33306:172.17.132.120:3306 jumper

遠程端口轉發

由遠程服務器的某個端口,轉發到本地網絡的服務器某個端口。說白了,就是將發送到遠程端口的請求,轉發到目標端口。格式如下:

ssh -R 遠程網卡地址:遠程端口:目標地址:目標端口 用戶@目標地址
常見的應用場景有個專用術語叫內網穿透,結構如下圖:

ssh_remote

# 將公網上的服務器 jump_target 的端口 33333 映射到本地的 22,這樣就可以通過在 jump_target 上通過 SSH 來訪問本地機器
ssh -f -N -g -R 33333:127.0.0.1:22 jump_target

TIPS:
公網上的服務器 jump_target 要設置 GatewayPorts yes,默認為 no。此外要映射的端口 33333 要可以訪問。

動態轉發

動態轉發就是建立一個SSH加密的SOCKS 4/5代理通道。任何支持 SOCKS 4/5 協議的程序都可以使用這個加密的通道進行訪問。格式如下:
ssh -D [本地地址:]本地端口號 遠程用戶@遠程地址

# 將訪問本地 55558 端口的請求都轉發給 jump_target ,并讓它去執行
ssh -C -N -g -T -D 127.0.0.1:55558 jump_target

日常使用問題

跳板機的配置

# 跳板機的配置
Host jump
  HostName  jumper.example.com
  Port      58422
  User      haojunyu
  IdentityFile ~/.ssh/dg_rsa
  AddKeysToAgent yes    # 將私鑰添加到 agent 中
  UseKeychain yes       # 保存密碼到 agent 中
# 目標機的配置
Host ws
  HostName  172.17.132.120
  Port      22
  User      haojunyu
  IdentityFile ~/.ssh/dg_rsa
  ProxyCommand ssh haojunyu@jump -W %h:%p 2>/dev/null
  ServerAliveInterval 10
  ServerAliveCountMax 3

內網任意服務訪問

日常工作中經常會啟很多服務在內網機器上,然后通過打洞(本地端口轉發)來將本地的端口映射到內網機器上服務端口。
這樣有個問題就是一個服務就得維持一個打洞命令 ssh -C -N -g -L 33306:172.17.132.120:3306 jumper
對應這樣的問題,最好的解決方案是使用動態轉發 ssh -C -N -g -T -D 127.0.0.1:55557 hb_jumper
本地通過 SwitchyOmega 或 proxifier 工具來將內網 IP 段 172.17.* 的請求轉發到本地的 55557 端口。

git push 報權限不允許(公鑰)

通常在服務器上執行 git push 時會報如下錯誤

具體報錯信息:
Permission denied (publickey).
fatal: Could not read from remote repository.

Please make sure you have the correct access rights and the repository exists.

報錯的原因是當前機器上沒有服務告訴 git 要使用哪個私鑰來進行 git 的操作。
對應的解決方法也比較多,推薦解法一和二:

  • 解法一:通過 ~/.ssh/config 指定(適用個人機器)

    Host github.com
        HostName  github.com
        User      haojunyu
        IdentityFile ~/.ssh/id_rsa
    
  • 解法二:配置倉庫或全局的 core.sshCommand(指定倉庫適用共享機器,全局適用個人機器.git版本高于2.3.0

    git config core.sshCommand "ssh -i ~/.ssh/id_rsa -F /dev/null"
    
  • 解法三:ssh-agent 臨時授權(適用共享機器)

    eval `ssh-agent`
    ssh-add ~/.ssh/id_rsa
    

端口轉發命令服務化

這個情況是希望開機時就把端口轉發開通,并且一直保持著。這就得介紹 linux 中常用的兩種服務化的工具:Supervisor 和 Systemd。
前者是需要安裝 Supervisor, 但工具比較輕量,使用也比較簡單,后者雖然比較重,但是基本所有系統都自帶。下面提供兩者的配置方法:

  • Supervisor 的配置
[program:ssh-wifi_ol]
command=ssh -C -N -g -L 9789:127.0.0.1:9789 jump
stdout_logfile=/Users/haojunyu/.supervisord_log/ssh-wifi_ol.log
autostart=true
autorestart=true
startsecs=5
priority=1
stopasgroup=true
killasgroup=true
  • Systemd 的配置
# gfw service
[Unit]
Description=gfw
After=network.target
[Service]
Type=simple
User=hjy
ExecStart=ssh -C -N -g -T -D 127.0.0.1:55558 gfw
Restart=on-failure
[Install]
WantedBy=multi-user.target

TIPS:
把一些經常用的服務通過端口轉發服務化,而一些臨時性的服務通過命令來進行端口轉發,也可以使用同事編寫的端口轉發的 Python 程序來進行。

參考文獻

  1. 什么是SSH?你應該用過吧
  2. 維基百科-SSH
  3. windows支持openssh
  4. 圖解SSH原理
  5. SSH官方文檔
  6. 所有配圖
  7. 中間人攻擊
  8. 了解ssh代理
  9. ssh遠程登陸中的鑰匙指紋是什么以及如何比對
  10. ssh登陸認證過程詳解

如果該文章對您產生了幫助,或者您對技術文章感興趣,可以關注微信公眾號: 技術茶話會, 能夠第一時間收到相關的技術文章,謝謝!

本篇文章由一文多發平臺ArtiPub自動發布

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,619評論 6 539
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,155評論 3 425
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,635評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,539評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,255評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,646評論 1 326
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,655評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,838評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,399評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,146評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,338評論 1 372
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,893評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,565評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,983評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,257評論 1 292
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,059評論 3 397
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,296評論 2 376

推薦閱讀更多精彩內容

  • 大綱 一、前言 今天又像打了雞血一樣,想好好學習了。正好看到一篇介紹http和https的文章,想到以前面試的時候...
    Python來了閱讀 1,877評論 0 3
  • 第1章 SSH服務 1.1 SSH服務協議說明 SSH 是 Secure Shell Protocol 的簡寫,由...
    喝可樂的貓兒閱讀 668評論 0 1
  • 遠程管理服務概念介紹 ssh 安全的遠程連接,數據信息是加密的 端口22 ssh默認root連接telnet...
    大仙兒沒溜兒閱讀 302評論 0 1
  • 37.day05--ssh遠程協議1.SSH基本概述SSH是一個安全協議,在進行數據傳輸時,會對數據包進行加密處理...
    優秀磚閱讀 2,433評論 0 0
  • 久違的晴天,家長會。 家長大會開好到教室時,離放學已經沒多少時間了。班主任說已經安排了三個家長分享經驗。 放學鈴聲...
    飄雪兒5閱讀 7,547評論 16 22