Kubernetes——安全認(rèn)證

Kubernetes集群安全機制說明

Kubernetes作為一個分布式集群的管理工具瞭稼,保證集群的安全性是其中一個重要的任務(wù),API Server是集群內(nèi)部各個組件通信的中介环肘,也是外部控制的入口。所以Kubernetes的安全機制基本就是圍繞保護API Server來設(shè)計的复哆。Kubernetes使用了認(rèn)證(Authentication)欣喧、鑒權(quán)(Authorization)梯找、準(zhǔn)入控制(Admission Control)三步來保證API Server的安全。


認(rèn)證(Authentication)

  • HTTP Token認(rèn)證:通過一個Token來識別合法用戶
    • HTTP Token的認(rèn)證是用一個很長的特殊編碼方式的并且難以被模仿的字符串-Token來表達客戶端的方式酷鸦,Token是一個很長的很復(fù)雜的字符串牙咏,每一個Token對應(yīng)一個用戶名存儲在API Server能訪問的文件中,當(dāng)客戶端發(fā)起API請求調(diào)用時妄壶,需要在HTTP Header里放入Token。
  • HTTP Base認(rèn)證:通過用戶名+密碼的方式認(rèn)證
    用戶名:密碼用BASE64算法進行編碼后的字符串放在HTTP Request中的Header Authorization域里發(fā)送給服務(wù)端丁寄,服務(wù)端收到后進行解碼,獲取用戶名和密碼盛正。
  • HTTPS 證書認(rèn)證:基于CA證書簽名的數(shù)字證書認(rèn)證

HTTPS 證書認(rèn)證

HTTPS 證書認(rèn)證

需要認(rèn)證的節(jié)點

需要認(rèn)證的節(jié)點

兩種類型

  • Kubernetes組件對API Server的訪問:kubectl屑埋、Controller Manager、Scheduler摘能、kubelet、kube-proxy
  • Kubernetes管理的Pod對容器的訪問:Pod(dashborad也是以Pod形式運行)

安全性說明

  • Controller Manager团搞、Scheduler與API Server在同一臺機器,所以直接使用API Server的非安全端口訪問--insecure-bind-address=127.0.0.1
  • kubectl像吻、kubelet梢莽、kube-proxy訪問API Server都需要證書進行HTTPS雙向認(rèn)證

證書頒發(fā)

  • 手動簽發(fā):通過K8s集群跟ca進行簽發(fā)HTTPS證書
  • 自動簽發(fā):kubelet首次訪問API Server時萧豆,使用token做認(rèn)證昏名,通過后Controller Manager會為kubelet生成一個證書以后的訪問都是用證書做認(rèn)證了。

kubeconfig

kubeconfig文件包含集群參數(shù)(CA證書轻局、API Server地址)样刷,客戶端參數(shù)(上面生成的證書和私鑰)览爵、集群Context信息(集群名稱、用戶名)蜓竹。Kubernetes組件通過啟動時指定不同的kubeconfig文件可以切換到不同的集群。

ServiceAccount

Pod中的容器訪問API Server嘶是,因為Pod的創(chuàng)建、銷毀是動態(tài)的聂喇,所以要為它手動生成證書就不可行了蔚携,Kubernetes使用了Service Account解決Pod訪問API Server的認(rèn)證問題。

Secret和CA的關(guān)系

Kubernetes設(shè)計了一種資源叫做Secret酝蜒,分為兩類,一種是用于ServiceAccount的service-account-token秕硝,另一種是用于保存用戶自定義保密信息的Oqaque洲尊,ServiceAccount中用到包含三個部分:Token、ca.crt坞嘀、namespace

  • Token:是使用了API Server私鑰簽名的JWT,用于訪問API Server時棺滞,Server端認(rèn)證
  • ca.crt:根證書,用于Client端驗證API Server發(fā)送的證書
  • namespace:標(biāo)識這個service-account-token的作用域名空間
    默認(rèn)情況下继准,每個namespace都會有一個ServiceAccount矮男,如果Pod在創(chuàng)建時沒有指定ServiceAccount,就會使用Pod所屬的namespace的ServiceAccount毡鉴。

鑒權(quán)(Authorization)

上面的認(rèn)證過程秒赤,只是確認(rèn)通信的雙方都確認(rèn)對方是可信的憎瘸,進而可以互相通信。
鑒權(quán)是確定請求方有哪些資源權(quán)限幌甘,API Server 內(nèi)部通過用戶認(rèn)證后,然后進入授權(quán)流程锅风。對合法用戶進行授權(quán)并且隨后在用戶訪問時進行鑒權(quán),是權(quán)限管理的重要環(huán)節(jié)盆均。API Server目前支持以下幾種授權(quán)策略(通過API Server的啟動參數(shù)--authorization-mode設(shè)置)

  • Always Deny: 表示拒絕所有的請求,一般用于測試泪姨。
  • Always Allow:允許接收所有請求饰抒,如果集群不需要授權(quán)流程,則可以采用該策略袋坑。
  • ABAC: 基于屬性的訪問控制,表示使用用戶配置的授權(quán)規(guī)則對用戶請求進行匹配和控制枣宫。
  • Webhook:通過調(diào)用外部REST服務(wù)對用戶進行授權(quán)。
  • RBAC:Role-Base Access Control也颤, 基于角色的訪問控制。

RBAC授權(quán)模式

RBAC(Role-Based Access Control文留,基于角色的訪問控制)在Kubernetes v1.5引入竭沫,在v1.6版本時升級為Beta版本燥翅,并成為kubeadm安裝方式下的默認(rèn)選項蜕提,組建其重要程度。相對于其他的訪問控制方式,RBAC具有如下優(yōu)勢躲查。

  • 對集群中的資源和非資源權(quán)限均有完整的覆蓋译柏。
  • 整個RBAC完全由幾個API對象完成镣煮,同其他API對象一樣鄙麦,可以用kubectl或API進行操作。
  • 可以在運行時進行調(diào)整胯府,無須重新啟動API Server。

要使用RBAC授權(quán)模式炎咖,則需要在API Server的啟動參數(shù)中加上--authorization-mode=RBAC寒波。


角色

  • Role:授權(quán)特定命名空間的訪問權(quán)限
  • ClusterRole:授權(quán)所有命名空間的訪問權(quán)限

角色綁定

  • RoleBinding:將角色綁定到主體(即subject)
  • ClusterRoleBinding:將集群角色綁定到主體

主體(subject)

  • User:用戶
  • Group:用戶組
  • ServiceAccount:服務(wù)賬號

1、RBAC的API資源對象說明

BAC引入了4個新的頂級資源對象:Role俄烁、ClusterRole、RoleBinding页屠、ClusterRoleBinding。同其他API資源對象一樣风纠,用戶可以使用kubectl或者API調(diào)用方式操作這些資源對象。


需要注意的是Kubernetes并不會提供用戶管理议忽,那么User十减、Group愤估、ServiceAccount指定的用戶又是從哪里來的呢帮辟?Kubernetes組件(kubectl玩焰、kube-proxy)或是其他自定義的用戶在向CA申請證書時,需要提供一個證書請求文件蔓榄。

[root@k8s-master1 ~]# vim jane-csr.json
{
  "CN": "admin",
  "hosts": [],
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "ST": "BeiJing",
      "L": "BeiJing",
      "O": "system:masters",
      "OU": "System"
    }
  ]
}
  • API Server會把客戶端證書的CN字段作為User并炮,把names.O字段作為Group
  • kubelet使用TLS Bootstaping認(rèn)證時甥郑,API Server可以使用 Bootstrap Tokens或者Token authentication file驗證=token,無論哪一種伍俘,Kubernetes都會為token綁定一個默認(rèn)的User和Group
  • Pod使用ServiceAccount認(rèn)證時,service-account-token中的JWT會保存User信息
  • 有了用戶信息癌瘾,在創(chuàng)建一對角色/角色綁定(集群角色/集群角色綁定)資源對象饵溅,就可以完成權(quán)限綁定了妨退。

Role and ClusterRole

在RBAC API中Role表示一組規(guī)則權(quán)限蜕企,權(quán)限只會增加(累加權(quán)限),不存在一個資源一開始就有很多權(quán)限而通過RBAC對其進行減少的操作糖赔;Role可以定義在一個namespace中,如果想要跨namespace則可以創(chuàng)建ClusterRole

kind: Role
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  namespace: default
  name: pod-reader
rules:
  - apiGroups: [""] # ""空字符串逝变,表示核心API群
    resources: ["pods"]
    verbs: ["get", "watch", "list"]

rules中的參數(shù)說明:

  • apiGroups: 支持的API組列表奋构,例如“apiVersion: batch/v1”壳影、“apiVersion: extensions:v1beta1”弥臼、“apiVersion: apps/v1beta1”等。
  • resources:支持的資源對象列表径缅,例如pods、deployments氧卧、jobs等。
  • verbs:對資源對象的操作方法列表沙绝,例如get、watch闪檬、list、delete粗悯、replace、patch等邮丰。

ClusterRole
ClusterRole處理具有和Role一致的命名空間內(nèi)資源的管理能力,因其集群級別的范圍剪廉,還可以用于以下特殊元素的授權(quán)炕檩。

  • 集群級別的資源控制斗蒋,例如Node(節(jié)點)笛质。
  • 非資源類型的路徑,例如“/healthz”妇押。
  • 包含全部命名空間的資源,例如pods(用于kubectl get pods --all-namespaces這樣的操作授權(quán))俊马。

下面的ClusterRole可以讓用戶有權(quán)訪問任意一個或所有命名空間的secrets(視其綁定方式而定):

kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  # ClusterRole不受限于命名空間肩杈,所以省略了namespace name的定義
  name: secret-reader
rules:
  - apiGroups: [""] # ""空字符串柴我,表示核心API群
    resources: ["secrets"]
    verbs: ["get", "watch", "list"]

角色綁定(RoleBinding)和集群角色綁定(ClusterRoleBinding)

RoleBinding可以將角色中定義的權(quán)限授予用戶或用戶組扩然,RoleBinding包含一組權(quán)限列表(subjects),權(quán)限列表中包含有不同形式的待授予權(quán)限資源類型(users夫偶、groups、Service Account)晕窑;RoleBinding同樣包含對被Bind的Role引用卵佛,RoleBinding適用于某個命名空間內(nèi)授權(quán),ClusterRoleBinding適用于集群范圍內(nèi)授權(quán)截汪。

下面例子中的RoleBinding將在default命名空間中把pod-reader角色授予用戶jane,這一操作讓jane可以讀取default命名空間中的Pod:

kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  namespace: default
  name: read-pods
subjects:
- kind: User
  name: jane
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io

RoleBinding也可以引用ClusterRole衙解,來對當(dāng)前namespace內(nèi)用戶、用戶組或ServiceAccount進行授權(quán)蚓峦,這種操作允許集群管理員在整個集群內(nèi)定義一些通用ClusterRole,然后在不同的namespace中使用RoleBinding來引用
例如暑椰,以下RoleBinding引用一個ClusterRole,這個ClusterRole具有整個集群內(nèi)對secrets的訪問權(quán)限一汽,但是其授權(quán)用戶dave只能訪問development空間中的secrets(因為RoleBinding定義在development命名空間)

kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  namespace: development
  name: read-secret
subjects:
- kind: User
  name: dave
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: secret-reader
  apiGroup: rbac.authorization.k8s.io

集群角色綁定中的角色只能是集群角色,用于進行集群級別或者對所有命名空間都生效的授權(quán)召夹。下面的例子允許manager組的用戶讀取任意namespace中的secret:

kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  namespace: development
  name: read-secrets-global
subjects:
- kind: Group
  name: manager
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: secret-reader
  apiGroup: rbac.authorization.k8s.io

資源(resources)與主體(subjects)

資源(resources)介紹

  • 在Kubernets中,主要的資源包括:Pods监憎、Nodes、Services鲸阔、Deployment、Replicasets腾它、Statefulsets死讹、Namespace瞒滴、Persistents赞警、Secrets和ConfigMaps等。
  • 同時愧旦,有些資源下面存在子資源,例如:Pod下就存在log子資源笤虫。
# logs資源就屬于pods的子資源祖凫,API中URL樣例如下
Get /api/v1/namespaces/{namespace}/pods/{name}/log

示例1:普通角色的資源列表:

[root@k8smaster01 study]# vi pod-and-pod_log.yaml
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  namespace: default
  name: pod-and-pod-logs-reader
rules:
  - apiGroups: [""]
    resources: ["pods","pods/log"]
    verbs: ["get","list"]

解釋:如上限定在default的命名空間的名為pod-and-pod-logs-reader的普通角色酬凳,對pod和pods/log資資源就有g(shù)et和list的權(quán)限。

示例2:更精細(xì)粒度的資源控制稠屠,可通過resourceNamess指定特定的資源實例,以限制角色只能夠?qū)唧w的某個實例進行訪問控制权埠。

[root@k8smaster01 study]# vi updater_configmap.yaml
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  namespace: default
  name: configmap-updater
rules:
  - apiGroups: [""]
    resources: ["configmaps"]
    resourceNames: ["my-configmap"]
    verbs: ["update","get"]

解釋:如上限定在default的命名空間的名為configmap-updater的普通角色煎谍,對名為my-configmap的configmaps類型的特定資源攘蔽,具有update和get權(quán)限粱快。

主體(subjects)介紹

  • RBAC授權(quán)中的主體可以是組,用戶或者服務(wù)帳戶事哭。用戶通過字符串表示,比如“alice”降盹、“bob@example.com”等,具體的形式取決于管理員在認(rèn)證模塊中所配置的用戶名蓄坏。
  • system: 被保留作為用來Kubernetes系統(tǒng)內(nèi)部使用丑念,因此不能作為用戶的前綴涡戳。組也有認(rèn)證模塊提供脯倚,格式與用戶類似。

示例1:類型為user(用戶)恍涂。

subjects:
  - kind: User
    name: "alice@example.com"
    apiGroup: rbac.authorization.k8s.io

示例2:類型為group(組)。

subjects:
  - kind: Group
    name: "frontend-admins"
    apiGroup: rbac.authorization.k8s.io

示例3:查看default的服務(wù)賬戶再沧。

subjects:
  - kind: ServiceAccount
    name: default
    namespace: kube-system

準(zhǔn)入控制

Kubernetes系統(tǒng)通過三個獨?的組件間的相互協(xié)作來實現(xiàn)服務(wù)賬戶的?動化尊残,三個組件具體為:Admission Controllers準(zhǔn)?控制器、令牌控制器(token controller)和Service Account賬戶控制器。Service Account控制器負(fù)責(zé)為名稱空間管理相應(yīng)的資源,并確保每個名稱空間中都存在?個名為“default”的Service Account對象。

當(dāng)請求通過了前面的認(rèn)證和授權(quán)之后钩蚊,還需要經(jīng)過準(zhǔn)入控制處理通過之后,apiserver 才會處理這個請求技俐。Admission Control 有一個準(zhǔn)入控制列表统台,我們可以通過命令行設(shè)置選擇執(zhí)行哪幾個準(zhǔn)入控制器。只有所有的準(zhǔn)入控制器都檢查通過之后井赌,apiserver 才執(zhí)行該請求贵扰,否則返回拒絕戚绕。

為什么需要Admission Control

在kubernetes中,一些高級特性正常運行的前提條件為耘子,將一些準(zhǔn)入模塊處于enable狀態(tài)球切。總結(jié)下捍歪,對于kubernetes apiserver怀骤,如果不適當(dāng)?shù)呐渲脺?zhǔn)入控制模塊蒋伦,他就不能稱作是一個完整的server,某些功能也不會正常的生效韧献。

主要的準(zhǔn)入控制器介紹

AlwaysAdmit

允許所有請求

AlwaysDeny

拒絕所有請求

AlwaysPullImages

強制設(shè)置Pod拉取鏡像策略為Always。這樣能夠保證私有鏡像只能被有拉取權(quán)限的使用者使用锤窑。

DenyExecOnPrivileged

它會攔截所有想在privileged container上執(zhí)行命令的請求。(如果自己的集群支持privileged container渊啰,自己又希望限制用戶在這些privileged container上執(zhí)行命令,那么強烈推薦使用它绘证。)

DenyEscalatingExec

這個插件禁止那些通過主機執(zhí)行而獲得privileges去執(zhí)行exec和attach Pod的命令。

ImagePolicyWebhook

通過webhook決定image策略嚷那,需要同時配置–admission-control-config-file

ServiceAccount

一個serviceAccount為運行在pod內(nèi)的進程添加了相應(yīng)的認(rèn)證信息胞枕。當(dāng)準(zhǔn)入模塊中開啟了此插件(默認(rèn)開啟),如果pod沒有serviceAccount屬性魏宽,將這個pod的serviceAccount屬性設(shè)為“default”腐泻;確保pod使用的serviceAccount始終存在;如果LimitSecretReferences 設(shè)置為true队询,當(dāng)這個pod引用了Secret對象卻沒引用ServiceAccount對象派桩,棄置這個pod;如果這個pod沒有包含任何ImagePullSecrets娘摔,則serviceAccount的ImagePullSecrets被添加給這個pod;如果MountServiceAccountToken為true凳寺,則將pod中的container添加一個VolumeMount 鸭津。

ResourceQuota

它會觀察所有的請求,確保在namespace中ResourceQuota對象處列舉的container沒有任何異常肠缨。如果在kubernetes中使用了ResourceQuota對象逆趋,就必須使用這個插件來約束container。(推薦在admission control參數(shù)列表中晒奕,這個插件排最后一個闻书。)

LimitRanger

實現(xiàn)配額控制。他會觀察所有的請求脑慧,確保沒有違反已經(jīng)定義好的約束條件魄眉,這些條件定義在namespace中LimitRange對象中。如果在kubernetes中使用LimitRange對象闷袒,則必須使用這個插件坑律。

SecurityContextDeny

禁止創(chuàng)建設(shè)置了 Security Context 的 pod。這個插件將會將使用了 SecurityContext的pod中定義的選項全部失效囊骤。關(guān)于 SecurityContext的描述:SecurityContext 在container中定義了操作系統(tǒng)級別的安全設(shè)定(uid, gid, capabilities, SELinux等等)晃择。

NamespaceLifecycle

確保處于termination狀態(tài)的namespace不再接收新的對象創(chuàng)建請求冀值,并拒絕請求不存在的namespace。

InitialResources

根據(jù)鏡像的歷史使用記錄宫屠,為容器設(shè)置默認(rèn)資源請求和限制

DefaultStorageClass

為PVC設(shè)置默認(rèn)StorageClass

DefaultTolerationSeconds

設(shè)置Pod的默認(rèn)forgiveness toleration為5分鐘

PodSecurityPolicy

使用Pod Security Policies時必須開啟

NodeRestriction

限制kubelet僅可訪問node列疗、endpoint、pod浪蹂、service以及secret抵栈、configmap、PV和PVC等相關(guān)的資源(v1.7版本以上才支持)

推薦的設(shè)置控制器順序:

--admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,ResourceQuota,DefaultTolerationSeconds

參考:
https://www.cnblogs.com/xzkzzz/p/9909468.html

https://www.cnblogs.com/Dev0ps/p/10852445.html

https://www.kubernetes.org.cn/1995.html

https://www.kubernetes.org.cn/4061.html

http://www.reibang.com/p/5a6e9ee8ab5a

http://www.reibang.com/p/fd61330596eb

https://www.cnblogs.com/itzgr/p/11112879.html

https://www.cnblogs.com/yanjieli/p/11859041.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末乌逐,一起剝皮案震驚了整個濱河市竭讳,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌浙踢,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,539評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件灿渴,死亡現(xiàn)場離奇詭異洛波,居然都是意外死亡,警方通過查閱死者的電腦和手機骚露,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,594評論 3 396
  • 文/潘曉璐 我一進店門蹬挤,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人棘幸,你說我怎么就攤上這事焰扳。” “怎么了误续?”我有些...
    開封第一講書人閱讀 165,871評論 0 356
  • 文/不壞的土叔 我叫張陵吨悍,是天一觀的道長。 經(jīng)常有香客問我蹋嵌,道長育瓜,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,963評論 1 295
  • 正文 為了忘掉前任栽烂,我火速辦了婚禮躏仇,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘腺办。我一直安慰自己焰手,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,984評論 6 393
  • 文/花漫 我一把揭開白布怀喉。 她就那樣靜靜地躺著书妻,像睡著了一般。 火紅的嫁衣襯著肌膚如雪磺送。 梳的紋絲不亂的頭發(fā)上驻子,一...
    開封第一講書人閱讀 51,763評論 1 307
  • 那天灿意,我揣著相機與錄音,去河邊找鬼崇呵。 笑死缤剧,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的域慷。 我是一名探鬼主播荒辕,決...
    沈念sama閱讀 40,468評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼犹褒!你這毒婦竟也來了抵窒?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤叠骑,失蹤者是張志新(化名)和其女友劉穎李皇,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體宙枷,經(jīng)...
    沈念sama閱讀 45,850評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡掉房,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,002評論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了慰丛。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片卓囚。...
    茶點故事閱讀 40,144評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖诅病,靈堂內(nèi)的尸體忽然破棺而出哪亿,到底是詐尸還是另有隱情,我是刑警寧澤贤笆,帶...
    沈念sama閱讀 35,823評論 5 346
  • 正文 年R本政府宣布蝇棉,位于F島的核電站,受9級特大地震影響苏潜,放射性物質(zhì)發(fā)生泄漏银萍。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,483評論 3 331
  • 文/蒙蒙 一恤左、第九天 我趴在偏房一處隱蔽的房頂上張望贴唇。 院中可真熱鬧,春花似錦飞袋、人聲如沸戳气。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,026評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽瓶您。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間呀袱,已是汗流浹背贸毕。 一陣腳步聲響...
    開封第一講書人閱讀 33,150評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留夜赵,地道東北人明棍。 一個月前我還...
    沈念sama閱讀 48,415評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像寇僧,于是被迫代替她去往敵國和親摊腋。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,092評論 2 355

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