懂了,原來 OkHttp 是這樣建立 HTTPS 連接的

目錄:

  1. 概述
  2. 基礎(chǔ)
    2.1. 加密
    2.2. 數(shù)字簽名
    2.3. 數(shù)字證書
  3. TLS 原理
  4. 主要的類和接口
    4.1. JDK
    4.2. OkHttp
  5. 源碼分析
    5.1. 創(chuàng)建安全 Socket
    5.2. 配置
    5.3. 握手
    5.4. 驗證
    5.5. 完成
  6. 應(yīng)用實例
    6.1. 信任所有證書
    6.2. 信任自簽名證書
    6.4. 自定義 TLS 連接規(guī)格
    6.5. 使用證書鎖定
  7. 資料

1. 概述

TLS 是進行 HTTPS 連接的重要環(huán)節(jié)震放,通過了 TLS 層進行協(xié)商,后續(xù)的 HTTP 請求就可以使用協(xié)商好的對稱密鑰進行加密

SSL 是 Netscape 開發(fā)的專門用來保護 Web 通訊驼修,目前版本為 3.0殿遂。TLS 是 IETF 制定的新協(xié)議,建立在 SSL 3.0 之上乙各。所以 TLS 1.0 可以認為是 SSL 3.1

TLS(Transport Layer Security Protocol) 協(xié)議分為兩部分

  • TLS 記錄協(xié)議
  • TLS 握手協(xié)議

2. 基礎(chǔ)

2.1. 加密

2.1.1. 對稱密鑰加密

編碼和解碼使用同一個密鑰墨礁,e = d

加密算法有

  • DES
  • Triple-DES
  • RC2
  • RC4(在 OkHttp 2.3 已經(jīng)下降支持)

位數(shù)越多,枚舉攻擊花費的時間越長

痛點:發(fā)送者和接收者建立對話前觅丰,需要一個共享密鑰

2.1.2. 非對稱密鑰加密

兩個密鑰,一個加密妨退,一個解密妇萄。私鑰持有,公鑰公開

  • RSA

破解私鑰的難度相當(dāng)于對極大數(shù)進行因式分解

RSA 加密系統(tǒng)中咬荷,D 和 E 會相互抵消

E(D(stuff)) = stuff
D(E(stuff)) = stuff

所以具體哪個是私鑰冠句,哪個是公鑰是由用戶選擇的

2.2 數(shù)字簽名

加了密的校驗和

  • 證明是原作者,只有原作者可以私鑰來進行加密
  • 證明沒有篡改幸乒,中途篡改校驗和就不再匹配

校驗和使用摘要算法生成懦底,比如 MD5,SHA

2.3. 數(shù)字證書

受信任組織擔(dān)保的用戶或公司的信息罕扎,沒有統(tǒng)一的標準

服務(wù)端大部分使用 x509 v3 派生證書聚唐,主要信息有

字段 舉例
證書序列號 12:34:56:78
證書過期時間 Wed,Sep 17,2017
站點組織名 StevenLee
站點DNS主機名 steven-lee.me
站點公鑰 xxxx
證書頒發(fā)者 RSA Data Security
數(shù)字簽名 xxxx

服務(wù)端把證書(內(nèi)含服務(wù)端的公鑰)發(fā)給客戶端,客戶端使用頒布證書的機構(gòu)的公鑰來解密腔召,檢查數(shù)字簽名杆查,取出公鑰。取出服務(wù)端的公鑰臀蛛,將后面請求用的對稱密鑰 X 傳遞給服務(wù)端亲桦,后面就用該密鑰進行加密傳輸信息

3. TLS 原理

HTTPS 是在 HTTP 和 TCP 之間加了一層 TLS,這個 TLS 協(xié)商了一個對稱密鑰來進行 HTTP 加密

TLS

同時浊仆,SSL/TLS 不僅僅可以用在 HTTP客峭,也可以用在 FTP,Telnet 等應(yīng)用層協(xié)議上抡柿。

SSL/TLS 實際上混合使用了對稱和非對稱密鑰舔琅,主要分成這幾步:

使用非對稱密鑰建立安全的通道

  • 客戶端請求 Https 連接洲劣,發(fā)送可用的 TLS 版本和可用的密碼套件
  • 服務(wù)端返回證書搏明,密碼套件和 TLS 版本

用安全的通道產(chǎn)生并發(fā)送臨時的隨機對稱密鑰鼠锈。

  • 生成隨機對稱密鑰,使用證書中的服務(wù)端公鑰加密星著,發(fā)送給服務(wù)端
  • 服務(wù)端使用私鑰解密獲取對稱密鑰

使用對稱密鑰加密信息购笆,進行交互

簡化后的流程圖如下:

TLS 握手

詳細的流程圖如下:

SSL Messages

4. 主要的類和接口

4.1. JDK

主要由 JDK 的 java.security虚循,javax.net 和 javax.net.ssl 提供的

  • SSLSocketFactory
  • SSLSocket
  • SSLSession
  • TrustManager
    • X509TrustManager
  • Certificate
    • X509Certificate
  • HostNameVerifier

核心類的關(guān)系圖

核心類圖

4.2. OkHttp

  • RealConnection
  • ConnectionSpecSelector
  • ConnectionSpec
  • CipherSuite
  • CertificatePinner

5. 源碼分析

連接的所有實現(xiàn)同欠,在 RealConnection 中。如果沒有從 ConnectionPool 復(fù)用横缔,創(chuàng)建新的連接過程铺遂,見 RealConnection.buildConnection:

private void buildConnection(int connectTimeout, int readTimeout, int writeTimeout, ConnectionSpecSelector connectionSpecSelector) throws IOException {
    connectSocket(connectTimeout, readTimeout);
    establishProtocol(readTimeout, writeTimeout, connectionSpecSelector);
}
  • connectSocket ,三次握手茎刚,創(chuàng)建 TCP 連接襟锐。

  • establishProtocol ,在 TCP 連接的基礎(chǔ)上膛锭,開始根據(jù)不同版本的協(xié)議粮坞,來完成連接過程。主要有 HTTP/1.1初狰,HTTP/2 和 SPDY 協(xié)議莫杈。如果是 HTTPS 類型的,則開始 TLS 建聯(lián)奢入。

  private void establishProtocol(int readTimeout, int writeTimeout,
      ConnectionSpecSelector connectionSpecSelector) throws IOException {
    if (route.address().sslSocketFactory() != null) {
      connectTls(readTimeout, writeTimeout, connectionSpecSelector);
    } else {
      protocol = Protocol.HTTP_1_1;
      socket = rawSocket;
    }
    ... 
  }

只關(guān)注 TLS 連接過程

 private void connectTls(int readTimeout, int writeTimeout,
      ConnectionSpecSelector connectionSpecSelector) throws IOException {
    Address address = route.address();
    SSLSocketFactory sslSocketFactory = address.sslSocketFactory();
    boolean success = false;
    SSLSocket sslSocket = null;
    try {
      // Create the wrapper over the connected socket.
      sslSocket = (SSLSocket) sslSocketFactory.createSocket(
          rawSocket, address.url().host(), address.url().port(), true /* autoClose */);

      // Configure the socket's ciphers, TLS versions, and extensions.
      ConnectionSpec connectionSpec = connectionSpecSelector.configureSecureSocket(sslSocket);
      if (connectionSpec.supportsTlsExtensions()) {
        Platform.get().configureTlsExtensions(
            sslSocket, address.url().host(), address.protocols());
      }

      // Force handshake. This can throw!
      sslSocket.startHandshake();
      Handshake unverifiedHandshake = Handshake.get(sslSocket.getSession());

      // Verify that the socket's certificates are acceptable for the target host.
      if (!address.hostnameVerifier().verify(address.url().host(), sslSocket.getSession())) {
        X509Certificate cert = (X509Certificate) unverifiedHandshake.peerCertificates().get(0);
        throw new SSLPeerUnverifiedException("Hostname " + address.url().host() + " not verified:"
            + "\n    certificate: " + CertificatePinner.pin(cert)
            + "\n    DN: " + cert.getSubjectDN().getName()
            + "\n    subjectAltNames: " + OkHostnameVerifier.allSubjectAltNames(cert));
      }

      // Check that the certificate pinner is satisfied by the certificates presented.
      address.certificatePinner().check(address.url().host(),
          unverifiedHandshake.peerCertificates());

      // Success! Save the handshake and the ALPN protocol.
      String maybeProtocol = connectionSpec.supportsTlsExtensions()
          ? Platform.get().getSelectedProtocol(sslSocket)
          : null;
      socket = sslSocket;
      source = Okio.buffer(Okio.source(socket));
      sink = Okio.buffer(Okio.sink(socket));
      handshake = unverifiedHandshake;
      protocol = maybeProtocol != null
          ? Protocol.get(maybeProtocol)
          : Protocol.HTTP_1_1;
      success = true;
    } catch (AssertionError e) {
      if (Util.isAndroidGetsocknameError(e)) throw new IOException(e);
      throw e;
    } finally {
      if (sslSocket != null) {
        Platform.get().afterHandshake(sslSocket);
      }
      if (!success) {
        closeQuietly(sslSocket);
      }
    }
  }

5.1. 創(chuàng)建安全 Socket

這里的安全 Socket 就是 SSLSocket筝闹,是握手成功后的 TCP Socket 進行的封裝。

如果 SSLSocketFactory 沒有自定義配置的話腥光,會使用 OkHttp 的默認創(chuàng)建关顷。比如在 OkHttpClient 中有這樣的代碼來構(gòu)造默認的 SSLSocketFactory

      X509TrustManager trustManager = systemDefaultTrustManager();
      this.sslSocketFactory = systemDefaultSslSocketFactory(trustManager);
      this.certificateChainCleaner = CertificateChainCleaner.get(trustManager);

systemDefaultSslSocketFactory 方法使用 SSLContext 來構(gòu)造 SSLSocketFactory

  private SSLSocketFactory systemDefaultSslSocketFactory(X509TrustManager trustManager) {
    try {
      SSLContext sslContext = SSLContext.getInstance("TLS");
      sslContext.init(null, new TrustManager[] { trustManager }, null);
      return sslContext.getSocketFactory();
    } catch (GeneralSecurityException e) {
      throw new AssertionError(); // The system has no TLS. Just give up.
    }
  }

這樣就是用了系統(tǒng)默認的 X509TrustManager。

該 SSLSocketFactory 為系統(tǒng) SDK 提供武福,包括它生產(chǎn)的 SSLSocket解寝,所以和系統(tǒng)平臺版本強相關(guān),底層為 OpenSSL 庫艘儒。對 TLS 版本的支持情況不一樣聋伦,接口也有所不同。

SSLSocket 配置信息有兩大類:

  • 支持的 TLS 協(xié)議
  • 支持的密碼套件(CipherSuite)

OkHttp 不包括自己的 SSL/TLS 庫界睁,所以 SSLSocket 使用 Android 提供的標準 SSLSocket

5.2. 配置

經(jīng)過上面創(chuàng)建過程后觉增,SSLSocket 已經(jīng)有了一些操作系統(tǒng)提供的默認配置。但不完全安全翻斟,OkHttp 會有自己的連接規(guī)格逾礁,來過濾掉過時的 TLS 版本和弱密碼套件。

OkHttp 內(nèi)置了三套規(guī)格,

  • ConnectionSepc.MODEN_TLS嘹履, 現(xiàn)代的 TLS 配置腻扇。
  • ConnectionSpec.COMPATIABLE_TLS,不是現(xiàn)代的砾嫉,但安全 TLS 配置幼苛。
  • ConnectionSpec.CLEARTEXT, 不安全的 TLS 配置焕刮。

這三套規(guī)格跟著版本走舶沿,例如,在OkHttp 2.2配并,下降支持響應(yīng)POODLE攻擊的SSL 3.0括荡。而在OkHttp 2.3 下降的支持RC4

所以與桌面Web瀏覽器,保持最新的OkHttp是保持安全的最好辦法

OkHttp 還會通過反射的方式溉旋,來對 SSLSocket 的 TLS 的擴展功能進行配置

  • SNI 和 Session tickets
  • ALPN

OkHttp 會先使用現(xiàn)代的規(guī)格(ConnectionSepc.MODEN_TLS)進行連接畸冲,如果失敗會采用回退策略選擇下一個。

5.2.1. TLS 連接規(guī)格選擇

該步驟選擇適合客戶端的 TLS連接規(guī)格观腊。一個很大的作用邑闲,就是盡可能地使用高版本的 TLS,和最新的密碼套件恕沫,來提供最安全的連接监憎。

連接規(guī)格都封裝在 ConnectionSpec 中纱意,主要內(nèi)容就是 TLS 版本和密碼套件

連接規(guī)格選擇的策略由 ConnectSpecSelector 進行婶溯,默認使用 OkHttp 的三套規(guī)格

最后會調(diào)用 ConnectionSpec 的 apply 方法,來配置 SSLSocket

/** Applies this spec to {@code sslSocket}. */
void apply(SSLSocket sslSocket, boolean isFallback) {
    ConnectionSpec specToApply = supportedSpec(sslSocket, isFallback);

    if (specToApply.tlsVersions != null) {
        sslSocket.setEnabledProtocols(specToApply.tlsVersions);
    }
    if (specToApply.cipherSuites != null) {
        sslSocket.setEnabledCipherSuites(specToApply.cipherSuites);
    }
}

在 supportedSpec 方法中偷霉,會對選擇好的規(guī)格迄委,和 SSLSocket 可用的配置取中交集,過濾掉那些不安全的低版本的 TLS 和弱密碼套件和 SSLSocket 不支持的配置类少。

這個階段后叙身,SSLSocket 中的一些不安全的 TLS 版本和弱密碼套件就被過濾了,將會使用 OkHttp 配置規(guī)范中認為的安全版本和強密碼套件開始正式的握手過程硫狞。

5.2.2. TLS 連接規(guī)格回退

最開始會嘗試現(xiàn)代的 TLS 規(guī)格信轿,如果不支持的話,會有回退策略(Fallback Strategy)残吩,回退到非現(xiàn)代但安全的 TLS 規(guī)格

回退策略由 RealConnection 和 ConnectSpecSelector 一起配合提供财忽。

比如它會先選擇最新的 ConnectionSpec.MODEN_TLS,不支持的話泣侮,再更換為 ConnectionSpec.COMPATIABLE_TLS即彪,最后選擇 ConnectionSpec.CLEARTEXT

策略很簡單活尊,就是連接失敗的時候隶校,更換下一套規(guī)范重新進行連接漏益。

5.2.3. TLS 擴展配置

Android 平臺,最終在 AndroidPlatform.configureTlsExtensions 來完成配置

@Override public void configureTlsExtensions(
    SSLSocket sslSocket, String hostname, List<Protocol> protocols) {
  // Enable SNI and session tickets.
  if (hostname != null) {
    setUseSessionTickets.invokeOptionalWithoutCheckedException(sslSocket, true);
    setHostname.invokeOptionalWithoutCheckedException(sslSocket, hostname);
  }

  // Enable ALPN.
  if (setAlpnProtocols != null && setAlpnProtocols.isSupported(sslSocket)) {
    Object[] parameters = {concatLengthPrefixed(protocols)};
    setAlpnProtocols.invokeWithoutCheckedException(sslSocket, parameters);
  }
}

因為某些手機機型是支持 TLS 擴展的深胳,OkHttp 采用發(fā)射的方式嘗試加載擴展绰疤,讓這些機型的擴展配置生效。

如果 ConectionSpec 支持 TLS 的擴展稠屠,這里還會配置 SNI峦睡,session tickets 和 ALPN。

5.3. 握手

調(diào)用 SSLSocket.startHandShake 開始進行握手:

// Force handshake. This can throw!
sslSocket.startHandshake();
Handshake unverifiedHandshake = Handshake.get(sslSocket.getSession());

這里客戶端正式向服務(wù)端發(fā)出數(shù)據(jù)包权埠,內(nèi)容為可選擇的密碼和請求證書榨了。服務(wù)端會返回相應(yīng)的密碼套件,tls 版本攘蔽,節(jié)點證書龙屉,本地證書等等,然后封裝在 Handshake 類中

主要內(nèi)容有:

  • CipherSuite满俗, 密碼套件转捕。
  • TlsVersion, TLS 版本唆垃。
  • Certificate[] peerCertificates五芝, 站點的證書。
  • Certificate[] localCertificates辕万, 本地的證書枢步。一些安全級別更高的應(yīng)用,會使用雙向的證書認證渐尿。

該過程中醉途,SSLSocket 內(nèi)部會對服務(wù)端返回的 Certificate 進行判斷,是否是可信任的 CA 發(fā)布的砖茸。如果不是的話隘擎,會拋出異常

5.4. 驗證

到了這一步,服務(wù)端返回的證書已經(jīng)被系統(tǒng)所信任凉夯,也就是頒發(fā)的機構(gòu) CA 在系統(tǒng)的可信任 CA 列表中了货葬。但是為了更加安全,還會進行以下兩種驗證劲够。

5.4.1. 站點身份驗證

使用 HostnameVerifier 來驗證 host 是否合法震桶,如果不合法會拋出 SSLPeerUnverifiedException

默認的實現(xiàn)是 OkHostnameVerifier.verify :

  public boolean verify(String host, SSLSession session) {
    try {
      Certificate[] certificates = session.getPeerCertificates();
      return verify(host, (X509Certificate) certificates[0]);
    } catch (SSLException e) {
      return false;
    }
  }

具體的驗證策略比較簡單,主要是檢查證書里的 IP 和 hostname 是否是我們的目標地址

5.4.2. 證書鎖定(Certificate Pinner)

到了該階段再沧,證書已經(jīng)被信任尼夺,是屬于平臺的可信任證書授權(quán)機構(gòu)(CA)的。但是這個會受到證書頒發(fā)機構(gòu)的攻擊,比如 2011 DigiNotar 的攻擊淤堵。

所以寝衫,還可以使用 CertificatePinner 來鎖定,哪些證書和 CA 是可信任的拐邪。

缺點慰毅,限制了服務(wù)端更新 TLS 證書的能力,所以證書鎖定一定要經(jīng)過服務(wù)端管理員的同意扎阶。

5.5. 完成

成功創(chuàng)建汹胃,保存這些信息:

  • Socket,安全的連接东臀。
  • Handshake着饥,握手信息。
  • Protocol惰赋,使用的 HTTP 協(xié)議宰掉。

后面和服務(wù)端的交互,都會被 TLS 過程中協(xié)商好的對稱密鑰進行加密赁濒。

6. 應(yīng)用實例

6.1. 信任所有證書

  • 跳過系統(tǒng)檢驗轨奄,不再使用系統(tǒng)默認的 SSLSocketFactory
  • 自定義 TrustManager,信任所有證書
X509TrustManager trustManager = new X509TrustManager() {
    @Override
    public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
    }

    @Override
    public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
    }

    @Override
    public X509Certificate[] getAcceptedIssuers() {
        return new X509Certificate[0];
    }
};

SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, new TrustManager[]{trustManager}, null);
SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();

OkHttpClient client = new OkHttpClient.Builder()
                        .sslSocketFactory(sslSocketFactory, trustManager)
                        .build();

Request request = new Request.Builder()
                    .url("https://kyfw.12306.cn/otn/")                    
                    .build();

Call call = client.newCall(request);
Response response = call.execute();

Logger.d("response " + response.code());

response.close();

6.2. 信任自簽名證書

還是以 12306 來進行測試拒炎,先從官網(wǎng)上下載證書 srca.cer

  • 將自簽名證書挪拟,比如 12306 的 srca.cer,保存到 assets
  • 讀取自簽名證書集合击你,保存到 KeyStore 中
  • 使用 KeyStore 構(gòu)建 X509TrustManager
  • 使用 X509TrustManager 初始化 SSLContext
  • 使用 SSLContext 創(chuàng)建 SSLSocketFactory
// 獲取自簽名證書集合玉组,由證書工廠管理
InputStream inputStream = HttpsActivity.this.getAssets().open("srca.cer");
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
Collection<? extends java.security.cert.Certificate> certificates = certificateFactory.generateCertificates(inputStream);
if (certificates.isEmpty()) {
    throw new IllegalArgumentException("expected non-empty set of trusted certificates");
}

// 將證書保存到 KeyStore 中
char[] password = "password".toCharArray();
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(null, password);
int index = 0;
for (Certificate certificate : certificates) {
    String certificateAlias = String.valueOf(index++);
    keyStore.setCertificateEntry(certificateAlias, certificate);
}

// 使用包含自簽名證書的 KeyStore 構(gòu)建一個 X509TrustManager
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(keyStore, password);
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(keyStore);

TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) {
    throw new IllegalStateException("Unexpected default trust managers:"
        + Arrays.toString(trustManagers));
}

// 使用 X509TrustManager 初始化 SSLContext
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, new TrustManager[]{trustManagers[0]}, null);
SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();

OkHttpClient client = new OkHttpClient.Builder()
                        .sslSocketFactory(sslSocketFactory, (X509TrustManager) trustManagers[0])
                        .build();

Request request = new Request.Builder()
                    .url("https://kyfw.12306.cn/otn/")
                    .build();

Call call = client.newCall(request);
Response response = call.execute();

Logger.d("response " + response.code());

response.close();

6.3. 自定義TLS連接規(guī)格

比如使用三個安全級別很高的密碼套件,并且限制 TLS 版本為 1_2

ConnectionSpec spec = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)  
    .tlsVersions(TlsVersion.TLS_1_2)
    .cipherSuites(
          CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
          CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
          CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256)
    .build();

OkHttpClient client = new OkHttpClient.Builder() 
    .connectionSpecs(Collections.singletonList(spec))
    .build();

該連接規(guī)格的配置是否能夠生效果漾,還需要和 SSLSocket 的支持情況取交集球切,SSLSocket 不支持也就用不了

所以這三個密碼套件只能在 Android 5.0 以上的機子生效了

6.4. 使用證書鎖定

比如鎖定了指定 publicobject.com 的證書谷誓。

pin 的取值為绒障,先對證書公鑰信息使用 SHA-256 或者 SHA-1 取哈希,然后進行 Base64 編碼捍歪,再加上 sha256 或者 sha1 的前綴户辱。

這樣 publicobject.com 只能使用指定公鑰的證書了,安全性進一步提高糙臼,但靈活性降低:

CertificatePinner certificatePinner = new CertificatePinner.Builder()
    .add("publicobject.com", "sha256/afwiKY3RxoMmLkuRW1l7QsPZTJPwDS2pdDROQjXw8ig=")
    .add("publicobject.com", "sha256/klO23nT2ehFDXCfx3eHTDRESMz3asj1muO+4aIdjiuY=")
    .add("publicobject.com", "sha256/grX4Ta9HpZx6tSHkmCrvpApTQGo67CYDnvprLg5yRME=")
    .add("publicobject.com", "sha256/lCppFqbkrlJ3EcVFAkeip0+44VaoJUymbnOaEUk7tEU=")
    .build();

OkHttpClient client = new OkHttpClient.Builder()
    .certificatePinner(certificatePinner)
    .build();

7. 資料

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末庐镐,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子变逃,更是在濱河造成了極大的恐慌必逆,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,544評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異名眉,居然都是意外死亡粟矿,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評論 3 392
  • 文/潘曉璐 我一進店門损拢,熙熙樓的掌柜王于貴愁眉苦臉地迎上來陌粹,“玉大人,你說我怎么就攤上這事福压√椭龋” “怎么了?”我有些...
    開封第一講書人閱讀 162,764評論 0 353
  • 文/不壞的土叔 我叫張陵荆姆,是天一觀的道長蒙幻。 經(jīng)常有香客問我,道長胆筒,這世上最難降的妖魔是什么杆煞? 我笑而不...
    開封第一講書人閱讀 58,193評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮腐泻,結(jié)果婚禮上决乎,老公的妹妹穿的比我還像新娘。我一直安慰自己派桩,他們只是感情好构诚,可當(dāng)我...
    茶點故事閱讀 67,216評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著铆惑,像睡著了一般范嘱。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上员魏,一...
    開封第一講書人閱讀 51,182評論 1 299
  • 那天丑蛤,我揣著相機與錄音,去河邊找鬼撕阎。 笑死受裹,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的虏束。 我是一名探鬼主播棉饶,決...
    沈念sama閱讀 40,063評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼镇匀!你這毒婦竟也來了照藻?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,917評論 0 274
  • 序言:老撾萬榮一對情侶失蹤汗侵,失蹤者是張志新(化名)和其女友劉穎幸缕,沒想到半個月后群发,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,329評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡发乔,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,543評論 2 332
  • 正文 我和宋清朗相戀三年也物,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片列疗。...
    茶點故事閱讀 39,722評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡滑蚯,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出抵栈,到底是詐尸還是另有隱情告材,我是刑警寧澤,帶...
    沈念sama閱讀 35,425評論 5 343
  • 正文 年R本政府宣布古劲,位于F島的核電站斥赋,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏产艾。R本人自食惡果不足惜疤剑,卻給世界環(huán)境...
    茶點故事閱讀 41,019評論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望闷堡。 院中可真熱鬧隘膘,春花似錦、人聲如沸杠览。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,671評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽踱阿。三九已至管钳,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間软舌,已是汗流浹背才漆。 一陣腳步聲響...
    開封第一講書人閱讀 32,825評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留佛点,地道東北人醇滥。 一個月前我還...
    沈念sama閱讀 47,729評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像恋脚,于是被迫代替她去往敵國和親腺办。 傳聞我的和親對象是個殘疾皇子焰手,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,614評論 2 353

推薦閱讀更多精彩內(nèi)容