Namespaces in Linux

本文是翻譯一篇國(guó)外博客的內(nèi)容:https://www.toptal.com/linux/separation-anxiety-isolating-your-system-with-linux-namespaces

隨著Docker捌蚊、Linux Containers等工具的出現(xiàn)渗饮,把Linux進(jìn)程隔離到進(jìn)程所屬的系統(tǒng)環(huán)境中變的很容易恢暖。讓一組程序在不需要虛擬機(jī)的情況下盯蝴,運(yùn)行在一個(gè)真實(shí)的Linux機(jī)器上并且這些程序不會(huì)互相影響變的完全有可能禁谦。這些工具對(duì)于PaaS供應(yīng)商來(lái)說(shuō)如虎添翼显设。但是到底發(fā)生了什么在這種現(xiàn)象下面?
這些工具依賴了一些Linux kernel的功能和組件涩盾。一些其中的功能是最近一段時(shí)間才發(fā)布的十气,并且需要給kernel打補(bǔ)丁才能使用。其中的一個(gè)重要的組建Linux namespaces是2.6.24版本中的一個(gè)功能春霍,這個(gè)版本在2008年發(fā)布砸西。
已經(jīng)熟悉chroot的人已經(jīng)有了一些關(guān)于Linux namespaces能做什么和怎么樣使用namespaces有了一個(gè)基本的認(rèn)知。chroot允許進(jìn)程作為root去訪問(wèn)任意目錄(不會(huì)影響其他的進(jìn)程), Linux namespaces允許操作系統(tǒng)的其他方面也變的可以獨(dú)立的被修改址儒,包括進(jìn)程樹(shù)芹枷、網(wǎng)絡(luò)接口,進(jìn)程間通信資源等离福。

為什么使用Namespaces隔離進(jìn)程

在只有一個(gè)用戶的計(jì)算機(jī)中杖狼,一個(gè)單獨(dú)的系統(tǒng)環(huán)境就可以滿足。但是在一個(gè)想要運(yùn)行多個(gè)服務(wù)的服務(wù)器中妖爷,各個(gè)服務(wù)是隔離運(yùn)行的是有必要的蝶涩,這樣會(huì)更加安全和穩(wěn)定。想象一種情況絮识,有一個(gè)服務(wù)器中運(yùn)行著多個(gè)服務(wù)绿聘,其中一個(gè)服務(wù)被入侵了,在這種情況下次舌,這個(gè)入侵者就能夠利用這個(gè)服務(wù)并以自己的方式去入侵其他服務(wù)熄攘,并且有可能對(duì)整個(gè)服務(wù)器都造成影響。Namespaces隔離可以提供一個(gè)安全的環(huán)境去排除這種風(fēng)險(xiǎn)彼念。
像Docker這種命名空間工具可以很好的控制進(jìn)程對(duì)系統(tǒng)資源的使用挪圾,PaaS提供商讓這些工具變的很流行。像Heroku和Google App Engine使用這些工具去隔離和運(yùn)行多個(gè)web服務(wù)在同一個(gè)真實(shí)的硬件上逐沙。這些工具允許他們?nèi)ミ\(yùn)行每一個(gè)程序并且不用擔(dān)心其中的程序使用了太多系統(tǒng)資源或者干擾運(yùn)行在同一臺(tái)機(jī)器上的程序活著發(fā)生沖突哲思。當(dāng)這些進(jìn)程隔離時(shí),甚至可以讓每個(gè)隔離環(huán)境擁有一套不同的依賴軟件集合吩案。
如果你已經(jīng)使用過(guò)了像Docker這樣的工具棚赔,你已經(jīng)知道了這些工具是有著把進(jìn)程隔離到一個(gè)小的containers的能力。運(yùn)行在Docker Container中的進(jìn)程就像運(yùn)行在虛擬機(jī)上徘郭,不過(guò)container是比虛擬機(jī)輕量許多靠益。一個(gè)典型的虛擬機(jī)是在你的操作系統(tǒng)上模仿硬件層,并且虛擬機(jī)會(huì)運(yùn)行另外一個(gè)操作系統(tǒng)在虛擬硬件層上残揉。這樣你可以運(yùn)行進(jìn)程在一個(gè)虛擬機(jī)內(nèi)胧后,并且完全和真正的操作系統(tǒng)隔離。但是虛擬機(jī)非常重抱环!從另一個(gè)方面講绩卤,Docker Container使用了一些真實(shí)的操作系統(tǒng)中重要的功能途样,包括napespaces,并確保類似于虛擬機(jī)的隔離級(jí)別濒憋,Docker Container并沒(méi)有模擬仿真硬件何暇,也不會(huì)讓一臺(tái)機(jī)器上運(yùn)行另一個(gè)操作系統(tǒng). 這讓Docker container變得很輕量。

Process Namespace 進(jìn)程命名空間

從歷史上看凛驮,Linux內(nèi)核一直維護(hù)著一個(gè)進(jìn)程樹(shù)裆站。這個(gè)樹(shù)包含了每一個(gè)指向運(yùn)行在父子層上的進(jìn)程的引用。給一個(gè)進(jìn)程足夠的權(quán)限和并滿足一些條件黔夭,這個(gè)進(jìn)程就可以訪問(wèn)其他進(jìn)程通過(guò)附著一個(gè)追蹤器宏胯,甚至可以殺死其它進(jìn)程。
根據(jù)Linux namespaces的介紹本姥,實(shí)現(xiàn)多個(gè)嵌套進(jìn)程樹(shù)變得有可能肩袍。每一個(gè)進(jìn)程樹(shù)可以擁有整個(gè)隔離的進(jìn)程集合。這樣能夠保證屬于某個(gè)進(jìn)程樹(shù)的進(jìn)程不會(huì)被訪問(wèn)或殺死婚惫,事實(shí)上氛赐,甚至無(wú)法知道其它兄弟或父進(jìn)程里面是否有進(jìn)程。
每一次Linux系統(tǒng)在啟動(dòng)的時(shí)候先舷,它都會(huì)從一個(gè)進(jìn)程ID是1的進(jìn)程開(kāi)始艰管。這個(gè)進(jìn)程是進(jìn)程樹(shù)的根,并且它通過(guò)執(zhí)行正確的維護(hù)工作和開(kāi)始正確的守護(hù)程序/服務(wù)初始化剩下的系統(tǒng)蒋川。所有的其它進(jìn)程都會(huì)在這個(gè)根進(jìn)程下運(yùn)行牲芋。進(jìn)程空間允許使用自己PID 1進(jìn)程衍生出新的進(jìn)程樹(shù)。執(zhí)行此操作的進(jìn)程保留在原始樹(shù)中的父進(jìn)程空間中捺球,但它使子進(jìn)程成為其自己的進(jìn)程樹(shù)的根缸浦。
在PID命名空間的隔離下,在子命名空間下的進(jìn)程沒(méi)有辦法知道父進(jìn)程的存在氮兵。然后裂逐,在父命名空間的進(jìn)程能夠看到在子命名空間的全部?jī)?nèi)容, 就好像這些進(jìn)程是在父命名空間內(nèi)。

父子命名空間

創(chuàng)建一個(gè)內(nèi)嵌子命名空間是可能的胆剧,一個(gè)進(jìn)程開(kāi)始一個(gè)子進(jìn)程在一個(gè)新的PID命名空間絮姆,并且這個(gè)子進(jìn)程創(chuàng)建出另外的進(jìn)程在新的PID命名空間醉冤,以此類推秩霍。
根據(jù)PID namespaces的介紹,單個(gè)進(jìn)程能夠關(guān)聯(lián)多個(gè)進(jìn)程蚁阳,每個(gè)進(jìn)程空間對(duì)應(yīng)一個(gè)進(jìn)程铃绒。在Linux的源碼中,我們能看到一個(gè)名字是pid的結(jié)構(gòu)體螺捐,這個(gè)結(jié)構(gòu)體原本是用來(lái)追蹤單個(gè)PID颠悬,現(xiàn)在通過(guò)使用一個(gè)名字是upid的結(jié)構(gòu)體用來(lái)追蹤多個(gè)PIDs矮燎。

struct upid {
  int nr;                     // the PID value
  struct pid_namespace *ns;   // namespace where this PID is relevant
  // ...
};

struct pid {
  // ...
  int level;                  // number of upids
  struct upid numbers[0];     // array of upids
};

想要?jiǎng)?chuàng)建一個(gè)新的PID命名空間,必須的調(diào)用clone()這個(gè)系統(tǒng)調(diào)用赔癌,并且傳入一個(gè)特殊的標(biāo)示CLONE_NEWPID诞外。然后一些在下面討論的其它命名空間可以使用unshare()系統(tǒng)調(diào)用創(chuàng)建,一個(gè)PID namespace只能在一個(gè)新的進(jìn)程被啟動(dòng)之后使用clone()創(chuàng)建灾票。一旦clone()被調(diào)用并傳入這個(gè)標(biāo)識(shí)峡谊,這個(gè)新進(jìn)程立即在一個(gè)新的PID namespace中運(yùn)行并且在一個(gè)新的進(jìn)程樹(shù)下面。這個(gè)過(guò)程是可以使用一個(gè)簡(jiǎn)單的C語(yǔ)言來(lái)演示的:

#define _GNU_SOURCE
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>

static char child_stack[1048576];

static int child_fn() {
  printf("PID: %ld\n", (long)getpid());
  return 0;
}

int main() {
  pid_t child_pid = clone(child_fn, child_stack+1048576, CLONE_NEWPID | SIGCHLD, NULL);
  printf("clone() = %ld\n", (long)child_pid);

  waitpid(child_pid, NULL, 0);
  return 0;
}

編譯并且使用root軟件運(yùn)行這個(gè)權(quán)限刊苍,你將會(huì)看到類似下面的輸出:

clone() = 5304
PID: 1

這個(gè)是1的PID是child_fn打印出來(lái)的.
雖然上面關(guān)于namespaces的代碼比起在其它語(yǔ)言中的“Hello, world”并沒(méi)有長(zhǎng)多少既们,但是在這背后很多事情會(huì)發(fā)生。clone()函數(shù)就如果你想象的那樣正什,會(huì)通過(guò)克隆當(dāng)前的進(jìn)程并且開(kāi)始執(zhí)行在child_fn()中的代碼創(chuàng)建一個(gè)新的進(jìn)程. 然后啥纸,在做這些的同時(shí),新進(jìn)程會(huì)從原來(lái)的進(jìn)程樹(shù)中分離婴氮,并且系統(tǒng)會(huì)為這個(gè)新進(jìn)程創(chuàng)建一個(gè)新的進(jìn)程樹(shù)斯棒。
用下面的函數(shù)去替換static int child_fn()函數(shù),可以把在被隔離的空間的父進(jìn)程的PID打印出來(lái):

static int child_fn() {
    println("Parent PIDL %ld\n", (long)getpid());
return 0;
}

運(yùn)行這個(gè)程序之后會(huì)看到下面的結(jié)果:

clone() = 11449
Parent PID: 0

注意這個(gè)在隔離空間的父進(jìn)程PID是0莹妒,表明這個(gè)進(jìn)程沒(méi)有父進(jìn)程名船。嘗試再一次運(yùn)行下面同樣的程序,這次旨怠,刪除在clone)()里的CLONE_NEWPID標(biāo)識(shí)

pid_t child_pid = clone(child_fn, child_stack+1048576, SIGCHLD, NULL);

這次渠驼,你看到的父進(jìn)程PID不再是0:

clone() = 11561
Parent PID: 11560

這只是我們這個(gè)博客里的第一步,這些進(jìn)程并沒(méi)有被限制訪問(wèn)其它共享資源鉴腻。例如迷扇,網(wǎng)絡(luò)接口:如果被上面代碼創(chuàng)建出的子進(jìn)程監(jiān)聽(tīng)80借口,它將會(huì)阻止所有其它在這個(gè)系統(tǒng)上的進(jìn)程去監(jiān)聽(tīng)爽哎。

Linux Network Namespace

Network namespaces在這變得很有用蜓席。一個(gè)網(wǎng)絡(luò)命名空間允許每個(gè)進(jìn)程去監(jiān)聽(tīng)一組完全不同的網(wǎng)絡(luò)接口,甚至每個(gè)網(wǎng)絡(luò)命名空間的環(huán)回接口也不同课锌。
使用CLONE_NEWNETclone()函數(shù)可以把一個(gè)進(jìn)程隔離到它自己的網(wǎng)絡(luò)命名空間厨内。

#define _GNU_SOURCE
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>


static char child_stack[1048576];

static int child_fn() {
  printf("New `net` Namespace:\n");
  system("ip link");
  printf("\n\n");
  return 0;
}

int main() {
  printf("Original `net` Namespace:\n");
  system("ip link");
  printf("\n\n");

  pid_t child_pid = clone(child_fn, child_stack+1048576, CLONE_NEWPID | CLONE_NEWNET | SIGCHLD, NULL);

  waitpid(child_pid, NULL, 0);
  return 0;
}

Output:

Original `net` Namespace:
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: enp4s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
    link/ether 00:24:8c:a1:ac:e7 brd ff:ff:ff:ff:ff:ff


New `net` Namespace:
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN mode DEFAULT group default
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00

這里發(fā)生了什么? 物理以太網(wǎng)設(shè)備 enp4s0 屬于全局網(wǎng)絡(luò)命名空間渺贤,正如在此命名空間運(yùn)行的“ip”工具所指示的那樣雏胃。然后,在新的網(wǎng)絡(luò)命名空間中的物理接口是不可用的志鞍。而且瞭亮,在原本網(wǎng)絡(luò)命名空間的回環(huán)設(shè)備是激活的,但是在子網(wǎng)絡(luò)命名空間是不可用的固棚。
為了在子命令空間中提供一個(gè)有用的網(wǎng)絡(luò)接口统翩,有必要去創(chuàng)建額外的虛擬網(wǎng)絡(luò)接口仙蚜,這個(gè)接口可以橫跨多個(gè)命名空間。一旦完成這些厂汗,就可以去創(chuàng)建以太網(wǎng)橋了委粉,甚至可以在命名空間之間路由數(shù)據(jù)包。最后娶桦,為了讓這些功能工作艳丛,一個(gè)rounting process必須運(yùn)行在全局網(wǎng)絡(luò)命名空間去接收來(lái)自物理接口的流量并且通過(guò)合適的虛擬接口把流量路由到正確的子網(wǎng)絡(luò)命名空間√宋桑或許你現(xiàn)在能明白了為什么類似于Docker的幫忙做了全部繁重的事情的工具如此受歡迎氮双!

network namespace

想要手動(dòng)做到這些,你可以創(chuàng)建一對(duì)虛擬以太網(wǎng)霎匈,它通過(guò)在父命名空間運(yùn)行一條命令來(lái)連接父子命名空間戴差。

ip link add name veth0 type veth peer name veth1 netns <pid>

這里,pid應(yīng)該被在子命名空間的進(jìn)程ID替換铛嘱,這個(gè)子命名空間可以被父命名空間看到暖释。運(yùn)行這個(gè)命令會(huì)建立一個(gè)類似于管道的連接在兩個(gè)命名空間之間。父命名空間維護(hù)著veth0墨吓,子命名空間維護(hù)著veth1球匕。任何從一端進(jìn)入的流量都會(huì)從另一端出來(lái),就像連接兩個(gè)真實(shí)節(jié)點(diǎn)的真實(shí)網(wǎng)卡那樣帖烘。因此亮曹,這邊的虛擬以太網(wǎng)連接必須被分配一個(gè)IP地址。

Mount Namespace

Linux為系統(tǒng)所有的掛載點(diǎn)維護(hù)了一個(gè)數(shù)據(jù)結(jié)構(gòu)秘症。它包含了一些類似下面的信息:那個(gè)磁盤分區(qū)被掛載了照卦,它們被掛載到了哪里,它們是否是可讀的等等乡摹。使用 Linux 命名空間役耕,可以克隆這種數(shù)據(jù)結(jié)構(gòu),以便不同命名空間下的進(jìn)程可以更改掛載點(diǎn)聪廉,而不會(huì)相互影響瞬痘。
創(chuàng)建一個(gè)隔離的掛載命名空間與執(zhí)行chroot()有著相似的效果。chroot()是一個(gè)不錯(cuò)的方法板熊,但是它并不能完全的隔離框全,并且它的作用只局限在root掛載點(diǎn)。創(chuàng)建一個(gè)隔離的掛載命名空間允許每一個(gè)隔離的進(jìn)程有完全不同的關(guān)于整個(gè)系統(tǒng)掛載點(diǎn)的視圖邻邮。這允許你為每個(gè)隔離的進(jìn)程設(shè)置不同的根掛載點(diǎn)以及被指定的其他掛載點(diǎn)竣况。小心的使用本教材克婶,你可以避免任何系統(tǒng)底層信息的泄漏筒严。


想要達(dá)到這種效果需要給clone()函數(shù)穿一個(gè)CLONE_NEWNS的標(biāo)識(shí)丹泉。

clone(child_fn, child_stack+1048576, CLONE_NEWPID | CLONE_NEWNET | CLONE_NEWNS | SIGCHLD, NULL)

在剛開(kāi)始的時(shí)候,子進(jìn)程能看到跟父進(jìn)程完全一樣的掛載點(diǎn)鸭蛙。但是子進(jìn)程位于一個(gè)新的掛載命名空間時(shí)摹恨,這個(gè)子進(jìn)程能掛載或者取消掛載任何想要掛載的內(nèi)容,并且這個(gè)改變不會(huì)影響到在這個(gè)系統(tǒng)中的父命名空間以及其他掛載命名空間娶视。例如晒哄,如果父進(jìn)程有一個(gè)特殊的磁盤分區(qū)掛載到了根節(jié)點(diǎn),這個(gè)隔離的進(jìn)程剛開(kāi)始將會(huì)看到相同的掛載到root節(jié)點(diǎn)的磁盤分區(qū)肪获,但是寝凌,當(dāng)隔離進(jìn)程嘗試將根分區(qū)更改為其他分區(qū)時(shí),隔離掛載命名空間的好處是顯而易見(jiàn)的孝赫,因?yàn)楦闹粫?huì)影響隔離掛載命名空間较木。

其它命名空間

還有一個(gè)其它的命名空間,user namespace青柄, IPC namespace伐债, UTS namespace, 進(jìn)程可以被隔離到其中致开。user namespace允許一個(gè)進(jìn)程在namespace中擁有root的權(quán)限峰锁,同時(shí)不能訪問(wèn)在命名空間之外的進(jìn)程。被IPC namespace隔離的進(jìn)程可以有自己的進(jìn)程間通信資源双戳,例如System V IPC 和 POSIX 消息虹蒋。UTS 命名空間隔離了系統(tǒng)的兩個(gè)特定標(biāo)識(shí)符:節(jié)點(diǎn)名和域名。
這有一個(gè)小例子展示UTS namespace是如何隔離的

#define _GNU_SOURCE
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/utsname.h>
#include <sys/wait.h>
#include <unistd.h>


static char child_stack[1048576];

static void print_nodename() {
  struct utsname utsname;
  uname(&utsname);
  printf("%s\n", utsname.nodename);
}

static int child_fn() {
  printf("New UTS namespace nodename: ");
  print_nodename();

  printf("Changing nodename inside new UTS namespace\n");
  sethostname("GLaDOS", 6);

  printf("New UTS namespace nodename: ");
  print_nodename();
  return 0;
}

int main() {
  printf("Original UTS namespace nodename: ");
  print_nodename();

  pid_t child_pid = clone(child_fn, child_stack+1048576, CLONE_NEWUTS | SIGCHLD, NULL);

  sleep(1);

  printf("Original UTS namespace nodename: ");
  print_nodename();

  waitpid(child_pid, NULL, 0);

  return 0;
}

這個(gè)程序產(chǎn)生下面的輸出:

Original UTS namespace nodename: XT
New UTS namespace nodename: XT
Changing nodename inside new UTS namespace
New UTS namespace nodename: GLaDOS
Original UTS namespace nodename: XT

在這里飒货, child_fn() 打印節(jié)點(diǎn)名千诬,將其更改為其他內(nèi)容,然后再次打印膏斤。 更改自然僅發(fā)生在新的 UTS 命名空間內(nèi)徐绑。

Cross-Namespace Communication 跨Namespace通信

建立一種在父子命名空間的通信是有必要的。這可能是為了在隔離的環(huán)境中進(jìn)行配置工作莫辨,或者只是保留從外部查看該環(huán)境狀況的能力傲茄。一種能夠做到這樣的方法是運(yùn)行一個(gè)SSH后臺(tái)程序在namespace中。你可以有一個(gè)隔離的SSH后臺(tái)程序在每一個(gè)網(wǎng)絡(luò)命名空間中沮榜。但是有多個(gè)SSH后臺(tái)程序運(yùn)行會(huì)使用很多重要的資源例如內(nèi)存盘榨。擁有一個(gè)特殊的“init”過(guò)程再次被證明是一個(gè)好主意的地方。
“init”進(jìn)程可以在父命名空間和子命名空間之間建立通信通道蟆融。該通道可以基于 UNIX 套接字草巡,甚至可以使用 TCP。想要?jiǎng)?chuàng)建一個(gè)跨越兩個(gè)不同掛載命名空間的UNIX套接字型酥,你需要先創(chuàng)建一個(gè)子進(jìn)程山憨,然后創(chuàng)建UNIX套接字查乒,然后把子進(jìn)程隔離到一個(gè)分割的掛載命名空間。但是怎么能先創(chuàng)建進(jìn)程之后再隔離它郁竟?Linux提供了unshare()玛迄。這個(gè)特殊的系統(tǒng)調(diào)用允許一個(gè)進(jìn)程將自己與原始命名空間隔離,而不是讓父進(jìn)程讓子進(jìn)程隔離棚亩。例如蓖议,下面的代碼有著跟上面提到的網(wǎng)絡(luò)命名空間同樣的效果:

#define _GNU_SOURCE
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>


static char child_stack[1048576];

static int child_fn() {
  // calling unshare() from inside the init process lets you create a new namespace after a new process has been spawned
  unshare(CLONE_NEWNET);

  printf("New `net` Namespace:\n");
  system("ip link");
  printf("\n\n");
  return 0;
}

int main() {
  printf("Original `net` Namespace:\n");
  system("ip link");
  printf("\n\n");

  pid_t child_pid = clone(child_fn, child_stack+1048576, CLONE_NEWPID | SIGCHLD, NULL);

  waitpid(child_pid, NULL, 0);
  return 0;
}

并且,由于“init”進(jìn)程是你自己設(shè)計(jì)的讥蟆,你可以先讓它做所有必要的工作勒虾,然后在執(zhí)行目標(biāo)子進(jìn)程之前將它自己與系統(tǒng)的其余部分隔離開(kāi)來(lái)。

結(jié)論

本教程只是對(duì)如何在 Linux 中使用命名空間的概述瘸彤。 它應(yīng)該讓您對(duì) Linux 開(kāi)發(fā)人員如何開(kāi)始實(shí)施系統(tǒng)隔離有一個(gè)基本的了解从撼,這是 Docker 或 Linux 容器等工具架構(gòu)的一個(gè)組成部分。在大多數(shù)情況下钧栖,使用現(xiàn)有的工具是一個(gè)很好的選擇低零,例如Docker,這些工具已經(jīng)眾所周知并經(jīng)過(guò)測(cè)試拯杠。 但在某些情況下掏婶,擁有你自己的、自定義的進(jìn)程隔離機(jī)制可能是有意義的潭陪,在這種情況下雄妥,本命名空間教程將極大地幫助你。
除了我在本文中介紹的之外依溯,還有更多的事情發(fā)生老厌,并且你可能希望通過(guò)更多方式來(lái)限制目標(biāo)進(jìn)程以增加安全性和隔離性。 不管如何黎炉,希望這可以作為一個(gè)有用的起點(diǎn)枝秤,對(duì)于那些有興趣了解更多關(guān)于 Linux 的命名空間隔離如何真正起作用的人。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末慷嗜,一起剝皮案震驚了整個(gè)濱河市淀弹,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌庆械,老刑警劉巖薇溃,帶你破解...
    沈念sama閱讀 206,482評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異缭乘,居然都是意外死亡沐序,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)策幼,“玉大人邑时,你說(shuō)我怎么就攤上這事÷⒕澹” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,762評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵绰寞,是天一觀的道長(zhǎng)到逊。 經(jīng)常有香客問(wèn)我,道長(zhǎng)滤钱,這世上最難降的妖魔是什么觉壶? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,273評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮件缸,結(jié)果婚禮上铜靶,老公的妹妹穿的比我還像新娘。我一直安慰自己他炊,他們只是感情好争剿,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,289評(píng)論 5 373
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著痊末,像睡著了一般蚕苇。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上凿叠,一...
    開(kāi)封第一講書(shū)人閱讀 49,046評(píng)論 1 285
  • 那天涩笤,我揣著相機(jī)與錄音,去河邊找鬼盒件。 笑死蹬碧,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的炒刁。 我是一名探鬼主播恩沽,決...
    沈念sama閱讀 38,351評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼翔始!你這毒婦竟也來(lái)了飒筑?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 36,988評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤绽昏,失蹤者是張志新(化名)和其女友劉穎协屡,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體全谤,經(jīng)...
    沈念sama閱讀 43,476評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡肤晓,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,948評(píng)論 2 324
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片补憾。...
    茶點(diǎn)故事閱讀 38,064評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡漫萄,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出盈匾,到底是詐尸還是另有隱情腾务,我是刑警寧澤,帶...
    沈念sama閱讀 33,712評(píng)論 4 323
  • 正文 年R本政府宣布削饵,位于F島的核電站岩瘦,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏窿撬。R本人自食惡果不足惜启昧,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,261評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望劈伴。 院中可真熱鬧密末,春花似錦、人聲如沸跛璧。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,264評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)追城。三九已至田炭,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間漓柑,已是汗流浹背教硫。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,486評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留辆布,地道東北人瞬矩。 一個(gè)月前我還...
    沈念sama閱讀 45,511評(píng)論 2 354
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像锋玲,于是被迫代替她去往敵國(guó)和親景用。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,802評(píng)論 2 345

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