墨穗app.notebase.cn
控制台
内容库
动态
管理
账户
U
用户
--
在线
v1.0.165 · 墨穗笔记
笔记

Notebase墨穗
静水流深,落墨成穗。

0笔记
0工具
30推荐

分类导航

按主题直达

编辑精选

站内用户贡献 · 真实笔记

最新收录

每日更新
继续浏览全部内容 →

笔记

0
加载中...

工具

0

此页用于记录用户反馈问题后的每一次改进

关于

笔记用法

“写笔记”支持四种格式——Word 文档、Excel 表格、Markdown、纯文本,起稿或二次编辑时都能随时切换,同一篇笔记想用哪种形态来记,都由你说了算。

md、txt、csv、json 这类纯文本则原样载入,不做多余加工。拿一张现成的表倒进来、改几笔、再导出去,等于白用一台免费的格式转换器。

要带走就在右上角点“下载”,可导出 PDF、Word、Markdown、Excel、TXT 等格式;列表卡片“⋯”菜单里,也有同样的下载入口。

工具用法

在“工具”页点“+ 上传工具”即可发布:填好名称与链接,再用 Markdown 把使用方法写清楚——能解决什么问题、怎么装、怎么用,比堆介绍实在。

要分发安装包就一并上传压缩包(ZIP、RAR、7Z、TAR.GZ,最大 35MB),别人在详情页一键下载;只放链接不带附件也可以。

工具按大家的收藏热度排序,好用的自然会被顶上来。发布后可在详情页或卡片菜单里编辑、下架。

隐藏笔记

写笔记时勾上“隐藏”,这篇就只存在于你自己的账号里:不进列表、不进搜索、不上首页精选,也不会出现在任何公开的页面,链接发给别人同样打不开。

适合放密码、草稿、日记这类只给自己看的内容;想公开,去“发布”打开它,把“隐藏”的勾去掉再保存,之后编辑会默认保持原状态,不会悄悄变回公开。

不想公开、只想临时给人看:点“分享”生成一条带密码和有效期的链接,到期自动失效,你也能随时撤销。

数据安全

你的内容会同时保存在多个副本上,系统定期做备份与完整性校验,再配合异地容灾机制:就算某台机器出问题,数据也不会丢,可以长期放心存放;特别重要的资料,仍建议你另外再留一份备份。

技术

全站跑在容器化、模块化的现代架构上,更新、部署、回滚都很快,扩展性和稳定性都按长期运营的标准来设计(Built for reliability, designed to scale)。

理念

这个网站最早只是一个人的笔记仓库,后来慢慢长成现在的知识中枢。设计上很克制——没有广告、没有追踪、没有推荐算法,只是干干净净地存放一些东西;既然做好了,就公开出来,万一有人用得上呢。

原则

不做大而全,不做平台梦,保持简单、保持克制、保持好奇。所有内容都由用户贡献、由用户维护:不会突然冒出付费墙,不会在角落塞广告位,也不会把你的数据卖给第三方。

更多

产品会持续迭代,站内日志页记录着每一次改动,改了什么都有迹可循;想了解这个站是怎么一步步走到今天的,翻翻日志就能看到来龙去脉。

举报

如果在这里看到涉嫌违规的内容,点对应卡片右侧的“举报”按钮就能提交,我们会尽快核实处理;也谢谢你花一点时间,一起把这里维护干净。

趋势

// 点击导航加载发现
归档
// 归档为空
最近浏览
// 暂无浏览记录
发布
// 加载中...
用户发布
// 加载中...
用户管理
// 加载中...
访问统计
// 加载中...
内容审核
// 加载中...
个人信息
// 加载中...
返回首页

如何在 Kubernetes 中使用 SPIFFE、SPIRE 和 Cilium 实现零信任工作负载身份

2026-07-07网络安全

你的网络策略说:“允许来自 10.0.1.45 的流量”。昨天,10.0.1.45 是你的支付服务。今天,经过一次滚动部署后,它变成了你的日志代理。你的支付服务现在在 10.0.1.89。Kubernetes 已经更新了所有 endpoints 和服务记录——但你的网络策略对此一无所知。它还在默默地放行流量,基于一个不再属于你原本想信任的工作负载的 IP 地址。

这就是工作负载身份问题。IP 地址不是身份,它们只是位置。而在 Kubernetes 集群中,位置一直在变。基于 IP 地址构建安全策略意味着,每次 Pod 被调度、重新调度或扩缩容时,你的安全姿态都在无声地退化。

解决方案是密码学工作负载身份:每个工作负载都获得一个由证书支持的身份,证明“我是谁”,而不是“我在哪”。服务在交换任何数据之前,先使用这些证书相互认证。如果证书不匹配,连接就会被拒绝,不管流量来自哪个 IP 地址。

这就是 SPIFFE 和 SPIRE 提供的功能。而 Cilium 通过 eBPF 实现了这一点,无需在每个 Pod 中注入 sidecar。

在这篇文章里,你会理解 SPIFFE 身份模型的工作原理,部署 SPIRE 来为工作负载签发密码学身份,并使用 Cilium 内置的 SPIRE 集成来实现服务间的双向 TLS(mTLS),而且完全不需要改动你的应用代码。

前置条件

  • 熟悉 Kubernetes RBAC 和 Pod 安全——这本手册涵盖了基础
  • 熟悉 TLS 证书和 Kubernetes Secrets——这本手册涵盖了 cert-manager 和证书概念
  • 已安装 Helm 3 和 Cilium CLI
  • 一个 kind 集群——你会在本文中创建一个全新的集群,并用 Cilium 作为 CNI
  • 耐心:这是本系列文章中我做过的最复杂的演示。SPIRE 的组件比之前所有内容都多。

所有演示文件都在配套的 GitHub 仓库中。

目录

  • 工作负载身份问题
  • SPIFFE 的工作原理
    • SPIFFE ID 和信任域
    • SVID:密码学身份文档
    • 信任包
  • SPIRE 的工作原理
    • SPIRE Server 和 SPIRE Agent
    • 节点证明
    • 工作负载证明
    • SVID 签发与轮换
  • Cilium 如何用 SPIFFE 实现双向 TLS
  • 演示 1:安装带有 SPIRE 集成的 Cilium
    • 步骤 1:安装 Cilium CLI
    • 步骤 2:创建一个没有默认 CNI 的 kind 集群
    • 步骤 3:安装启用了 SPIRE 的 Cilium
    • 步骤 4:验证安装
  • 演示 2:用 CiliumNetworkPolicy 强制双向 TLS
    • 步骤 1:部署客户端和服务器
    • 步骤 2:确认没有认证时流量正常
    • 步骤 3:应用要求双向认证的 CiliumNetworkPolicy
    • 步骤 4:验证经过认证的流量仍然正常
    • 步骤 5:(可选)用 Hubble 观察认证过程
    • 步骤 6:验证没有匹配标签的 Pod 被拦截
    • 步骤 7:检查 SPIRE 中的工作负载条目
  • 结论
  • 清理(kind 集群)

工作负载身份问题

开头那个场景不是理论上的。在 Kubernetes 里,Pod 是短暂的。调度器可以把 Pod 放在任意节点上,而 Pod 的 IP 地址是在调度时从节点的 IP 池中分配的。当 Pod 因滚动部署、节点腾空或自动扩缩容事件被删除并重建时,它会获得一个新的 IP 地址。

如果你写了一个 NetworkPolicy,说“允许来自这个 IP 的流量”,那么这个策略现在要么指向了空,要么更糟——指向了一个不同的工作负载。

Kubernetes Service 名称在东西向流量上确实有帮助——无论后端是哪些 Pod,Service 名称都能一致地解析。但基于 Service 名称的 NetworkPolicy 本质上还是标签选择器匹配,而不是密码学断言。任何能伪造正确标签的 Pod 都可以绕过它。

你真正想要的是:在服务 A 向服务 B 发送请求之前,服务 B 必须用密码学方式证明自己的身份。如果服务 B 无法证明它是它所声称的那个服务,服务 A 就拒绝连接。这就是双向 TLS(mTLS)。而关键问题是:这些身份从哪里来?

SPIFFE 回答了这个问题。

SPIFFE 的工作原理

SPIFFE——Secure Production Identity Framework for Everyone——是一个 CNCF 标准,定义了一套工作负载身份模型。它本身不实现任何东西。它规定了身份的格式、请求身份的 API,以及使身份在服务、集群和云之间可验证的信任模型。

SPIRE 是该规范的参考实现。

SPIFFE ID 和信任域

SPIFFE 身份是一个 URI,格式如下:

spiffe://<trust-domain>/<workload-path>

信任域是一个字符串,标识管理边界——通常是你的组织、集群或环境。同一个信任域内的所有实体可以互相验证身份。来自不同信任域的身份需要显式的联邦配置。

一些具体的例子:

spiffe://payments.corp/ns/production/sa/checkout
spiffe://analytics.corp/ns/data/sa/pipeline-worker
spiffe://cluster.local/ns/monitoring/sa/prometheus

信任域后面的路径是任意的——由你的 SPIRE 配置定义,通常编码了 Kubernetes 命名空间和服务账户。

SVID:密码学身份文档

SVID——SPIFFE Verifiable Identity Document——是将 SPIFFE 身份具体化为服务可以实际使用的东西。有两种 SVID 格式:

  • X.509 SVID:一个标准的 TLS 证书,其中 SPIFFE ID 嵌入在 Subject Alternative Name (SAN) URI 字段中。因为是标准 X.509 证书,任何 TLS 库都可以直接使用。工作负载在 TLS 握手时出示此证书,对端验证证书是由受信任的 SPIRE Server 签名的。这是用于长连接(如 gRPC 流)的格式。
  • JWT SVID:一个签名的 JSON Web Token,其中 SPIFFE ID 作为声明。适合基于请求的 HTTP 认证——放在 Authorization 头中传递,接收服务验证签名。JWT SVID 的寿命比 X.509 SVID 短,并且限定在特定受众,以防止令牌跨服务重用。

对于 Cilium 的互相认证,使用 X.509 SVID。本文其余部分聚焦于 X.509。

信任包

为了让服务 A 验证服务 B 的证书,服务 A 需要知道哪个证书颁发机构(CA)签署了它。在 SPIFFE 中,这被称为信任包——一个信任域内受信任的 CA 证书集合。

SPIRE 通过 Workload API 提供信任包。当工作负载请求其身份时,它也会收到当前的信任包。当 SPIRE Server 轮换其 CA 时,它会将新的信任包分发给所有 Agent,再由 Agent 推送给所有工作负载。你的应用程序永远不需要手动管理信任包。

SPIRE 的工作原理

SPIRE 是签发 SVID 并管理身份生命周期的引擎。理解它的架构是理解 Cilium 集成的关键。

SPIRE Server 和 SPIRE Agent

SPIRE 有两个主要组件:

  • SPIRE Server:中央 CA。它维护一个工作负载条目注册表(描述应该向哪些工作负载签发哪些 SPIFFE ID)。它代表工作负载向 Agent 签发 SVID,是整个信任域的信任根。
  • SPIRE Agent:作为 DaemonSet 在每个节点上运行。它有两个任务:
    1. 向 SPIRE Server 证明它运行在一个合法的节点上——这叫节点证明。
    2. 在节点上通过 Unix 套接字暴露 SPIFFE Workload API,工作负载通过它请求自己的 SVID。

Agent 会在本地缓存 SVID,这样即使暂时与 SPIRE Server 断开连接,也不会立即破坏工作负载身份。

这种设计——中央 Server,每个节点上的 Agent——是有意为之的。工作负载从不直接联系 SPIRE Server,而是通过本地的 SPIRE Agent 获取身份。这减少了 SPIRE Server 的负载,同时提供了更好的容错性和可扩展性。

节点证明

节点证明是 SPIRE Agent 向 SPIRE Server 证明自己运行在合法节点上的过程。具体机制取决于平台:

  • 在 AWS 上,Agent 可以展示其 EC2 实例的元数据
  • 在 GCP 上,Agent 可以展示其 GCE 实例的元数据
  • 在 Kubernetes 上,Agent 使用 Kubernetes 的节点身份和令牌

一旦 Agent 被证明,它就能代表该节点上的工作负载请求 SVID。

工作负载证明

工作负载证明是 SPIRE Agent 识别哪个进程在请求身份的过程。在 Kubernetes 中,这通常基于 Pod 的标签、服务账户、命名空间等元数据。

当 Pod 中的工作负载通过 Unix 套接字向 SPIRE Agent 请求 SVID 时,Agent 会检查调用者的凭证——例如,它可以通过 cgroups 或 Linux 安全模块来确定调用进程属于哪个 Pod——然后根据 SPIRE Server 上配置的工作负载条目来决定是否签发身份。

SVID 签发与轮换

当工作负载第一次请求 SVID 时,SPIRE Agent 向 SPIRE Server 发起 CSR(证书签名请求)。Server 验证请求是来自一个被授权的工作负载,然后签发证书。

SPIRE 会自动轮换 SVID。默认情况下,X.509 SVID 的有效期是 1 小时,Agent 会在过期前自动请求新的证书。这意味着即使私钥泄露,影响范围也限制在很短的时间内。

Cilium 如何用 SPIFFE 实现双向 TLS

Cilium 是一个基于 eBPF 的网络、安全和可观测性项目。它原生支持 SPIFFE/SPIRE,无需 sidecar 即可实现工作负载间的双向 TLS。

Cilium 的 SPIRE 集成工作原理如下:

  1. 身份获取:Cilium 在每个节点上运行一个 SPIRE Agent(作为 Cilium Agent 的一部分或独立运行)。当 Pod 启动时,Cilium 会代表该 Pod 向 SPIRE Server 请求一个 SVID。
  2. 身份映射:Cilium 将 SPIFFE ID 映射到其内部的安全身份(Security Identity),这是一个整数 ID,用于 eBPF 策略决策。
  3. 策略执行:当你创建一个 CiliumNetworkPolicy 并指定 requireAuthentication 时,Cilium 会在 eBPF 层面强制要求连接必须经过 TLS 握手并验证对端的 SPIFFE ID。
  4. 透明代理:Cilium 使用 eBPF 在数据路径上透明地拦截流量,执行 TLS 握手,而不需要修改或重新配置应用程序。应用代码完全不知道 mTLS 的存在。

这意味着你可以为现有工作负载启用 mTLS,而无需更改一行代码或重新部署。

演示 1:安装带有 SPIRE 集成的 Cilium

让我们动起手来。先创建一个 kind 集群并安装 Cilium,启用 SPIRE 集成。

步骤 1:安装 Cilium CLI

如果你还没有安装 Cilium CLI,先从 GitHub 发布页面下载:

# Linux 或 macOS
curl -L --remote-name-all https://github.com/cilium/cilium-cli/releases/latest/download/cilium-linux-amd64.tar.gz{,.sha256sum}
sha256sum --check cilium-linux-amd64.tar.gz.sha256sum
sudo tar xzvfC cilium-linux-amd64.tar.gz /usr/local/bin
rm cilium-linux-amd64.tar.gz{,.sha256sum}

或者使用 Homebrew:

brew install cilium-cli

验证安装:

cilium version

你应该看到类似这样的输出:

cilium-cli: v0.16.6 compiled with go1.22.2 on linux/amd64
cilium image (default): v1.16.1
cilium image (stable): v1.16.1

步骤 2:创建一个没有默认 CNI 的 kind 集群

创建一个 kind 配置文件,禁用默认的 CNI,这样 Cilium 可以接管网络:

# kind-config.yaml
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
networking:
  disableDefaultCNI: true
nodes:
  - role: control-plane
  - role: worker

创建集群:

kind create cluster --config kind-config.yaml

等待节点就绪:

kubectl get nodes

你应该看到两个节点(一个 control-plane,一个 worker)都处于 Ready 状态,但 Pod 网络还没有就绪(CoreDNS 会处于 Pending 状态)。

步骤 3:安装启用了 SPIRE 的 Cilium

现在安装 Cilium,启用 SPIRE 集成:

cilium install \
  --set=spire.enabled=true \
  --set=spire.install.enabled=true \
  --set=spire.install.server.serviceType=ClusterIP

这个命令会:

  • 安装 Cilium 作为 CNI
  • 安装 SPIRE Server 和 SPIRE Agent(作为 Cilium 的一部分)
  • 配置 SPIRE 与 Cilium 的集成

等待安装完成:

cilium status --wait

你应该看到所有组件都处于健康状态,包括 spire-server 和 spire-agent。

步骤 4:验证安装

检查 SPIRE 相关的 Pod 是否正常运行:

kubectl get pods -n cilium-spire

你应该看到类似这样的输出:

NAME                              READY   STATUS    RESTARTS   AGE
spire-server-0                    1/1     Running   0          2m
spire-agent-6j4k8                 1/1     Running   0          2m
spire-agent-7x9qz                 1/1     Running   0          2m

验证 Cilium 的 SPIRE 集成:

kubectl exec -n cilium-spire spire-server-0 -- /opt/spire/bin/spire-server entry show

目前应该没有工作负载条目,因为还没有部署任何工作负载。

演示 2:用 CiliumNetworkPolicy 强制双向 TLS

现在让我们部署一个客户端和服务器,然后应用一个要求双向认证的网络策略。

步骤 1:部署客户端和服务器

创建一个命名空间:

kubectl create ns demo

创建服务器部署和 Service。这是一个简单的 HTTP 服务器,监听 8080 端口:

# server.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: http-server
  namespace: demo
spec:
  replicas: 1
  selector:
    matchLabels:
      app: http-server
  template:
    metadata:
      labels:
        app: http-server
    spec:
      containers:
      - name: http-server
        image: hashicorp/http-echo:latest
        args:
          - "-text=Hello from the server!"
          - "-listen=:8080"
        ports:
        - containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
  name: http-server
  namespace: demo
spec:
  selector:
    app: http-server
  ports:
  - port: 8080
    targetPort: 8080

创建客户端部署。这是一个简单的 curl Pod,用来测试连接:

# client.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: http-client
  namespace: demo
spec:
  replicas: 1
  selector:
    matchLabels:
      app: http-client
  template:
    metadata:
      labels:
        app: http-client
    spec:
      containers:
      - name: http-client
        image: curlimages/curl:latest
        command: ["/bin/sh", "-c", "sleep infinity"]

应用这两个部署:

kubectl apply -f server.yaml -f client.yaml

等待 Pod 就绪:

kubectl wait --for=condition=ready pod -l app=http-server -n demo
kubectl wait --for=condition=ready pod -l app=http-client -n demo

步骤 2:确认没有认证时流量正常

先测试从客户端到服务器的 HTTP 请求,确认网络是通的:

kubectl exec -n demo deploy/http-client -- curl -s http://http-server.demo.svc.cluster.local:8080

你应该看到:

Hello from the server!

流量正常。目前没有认证要求。

步骤 3:应用要求双向认证的 CiliumNetworkPolicy

现在创建 CiliumNetworkPolicy,要求客户端和服务器之间必须进行互相认证:

# mtls-policy.yaml
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
  name: "require-mtls"
  namespace: demo
spec:
  endpointSelector:
    matchLabels:
      app: http-server
  ingress:
  - fromEndpoints:
    - matchLabels:
        app: http-client
    authentication:
      mode: required

这个策略的意思是:

  • 目标(endpointSelector):选择 app=http-server 的 Pod
  • 入站规则:仅允许来自 app=http-client 的 Pod 的流量
  • 认证要求:必须进行互相认证(authentication.mode: required)

注意:authentication.mode 可以设置为 required 或 disabled。required 意味着 Cilium 会强制进行 TLS 握手,并验证对端的 SPIFFE ID。

应用策略:

kubectl apply -f mtls-policy.yaml

步骤 4:验证经过认证的流量仍然正常

现在再次测试从客户端到服务器的连接:

kubectl exec -n demo deploy/http-client -- curl -s http://http-server.demo.svc.cluster.local:8080

你应该仍然看到:

Hello from the server!

流量仍然正常,但现在它在幕后经过了 mTLS 认证。注意:应用程序代码没有改变,客户端也没有显式配置证书。Cilium 在 eBPF 层面透明地处理了 TLS 握手。

步骤 5:(可选)用 Hubble 观察认证过程

如果你安装了 Hubble,可以用它来观察认证过程。先启用 Hubble:

cilium hubble enable

然后启动 Hubble UI 或使用 CLI:

# 安装 Hubble CLI
# 然后观察流量
hubble observe --from-pod demo/http-client --to-pod demo/http-server

你应该看到类似这样的输出:

Sep 10 12:00:00.000  demo/http-client:8080  ->  demo/http-server:8080  to-endpoint  FORWARDED  (TCP)

注意流量被标记为 FORWARDED,因为认证成功。

步骤 6:验证没有匹配标签的 Pod 被阻止

现在创建一个没有正确标签的 Pod,尝试访问服务器:

# malicious-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: malicious-pod
  namespace: demo
  labels:
    app: malicious
spec:
  containers:
  - name: curl
    image: curlimages/curl:latest
    command: ["/bin/sh", "-c", "sleep infinity"]

创建这个 Pod:

kubectl apply -f malicious-pod.yaml
kubectl wait --for=condition=ready pod malicious-pod -n demo

尝试从恶意 Pod 访问服务器:

kubectl exec -n demo malicious-pod -- curl -s http://http-server.demo.svc.cluster.local:8080

这次请求应该被阻塞。你会看到类似这样的错误(或者连接超时):

curl: (28) Failed to connect to http-server.demo.svc.cluster.local port 8080 after 1000 ms: Connection timed out

这说明 CiliumNetworkPolicy 正确地阻止了未经认证的流量。恶意 Pod 没有正确的标签,因此无法通过策略检查,更无法完成 mTLS 握手。

步骤 7:检查 SPIRE 中的工作负载条目

最后,检查 SPIRE Server 中的工作负载条目,看看 Cilium 为你注册了哪些身份:

kubectl exec -n cilium-spire spire-server-0 -- /opt/spire/bin/spire-server entry show

你应该看到类似这样的输出:

Entry ID         : 12345678-1234-1234-1234-123456789abc
SPIFFE ID        : spiffe://cluster.local/ns/demo/sa/default
Parent ID        : spiffe://cluster.local/ns/cilium-spire/sa/spire-agent
TTL              : 3600
Selector         : k8s:pod-label:app:http-server
Selector         : k8s:ns:demo

注意:

  • SPIFFE ID 是 spiffe://cluster.local/ns/demo/sa/default——这表示命名空间 demo 中的默认服务账户
  • TTL 是 3600 秒(1 小时),之后 SVID 会自动轮换
  • Selector 指定了哪些 Pod 会获得这个身份——这里是标签 app=http-server 且在命名空间 demo 中的 Pod

Cilium 会自动为每个工作负载创建这样的条目。你不需要手动注册。

结论

我们在这篇文章中做了很多事:

  1. 理解了为什么 IP 地址不能作为身份——Pod 的 IP 是动态的,基于 IP 的安全策略会随着 Pod 调度和重新调度而失效
  2. 学习了 SPIFFE 身份模型——SPIFFE ID 是 URI 格式的身份标识,SVID 是具体的证书或令牌,信任包是 CA 证书集合
  3. 了解了 SPIRE 的架构——SPIRE Server 是中央 CA,SPIRE Agent 在每个节点上运行,工作负载通过本地 Agent 获取身份
  4. 看到了 Cilium 如何通过 eBPF 透明地实现 mTLS——无需 sidecar,无需修改应用代码
  5. 通过两个演示,实际部署了 Cilium + SPIRE,并验证了 mTLS 策略的效果

关键收获是:零信任不是关于信任网络位置,而是关于验证身份。SPIFFE 和 SPIRE 提供了标准化的身份框架,Cilium 将其与高性能的 eBPF 数据路径结合起来,让你可以在不牺牲性能或增加复杂性的情况下,为 Kubernetes 工作负载启用 mTLS。

清理

如果你使用的是 kind 集群,删除集群很简单:

kind delete cluster

这会删除整个集群,包括所有 Pod、Service 和存储。

如果你想保留集群但删除演示资源:

kubectl delete ns demo
kubectl delete -n cilium-spire $(kubectl get entries -n cilium-spire -o name)

但最简单的还是直接删掉整个 kind 集群。

相似推荐
用另一台手机远程帮人弄手机:林林远程控制,安卓被控 + 浏览器/小程序主控安卓补装 Google 三件套:服务框架 + Play 商店,附安装器与步骤VPS节点一键部署+本地订阅转换脚本苹果硬刚英国政府:撤销iCloud高级数据保护,一场加密与主权的全球博弈压迫还是诈骗?AdGuard DNS 对 Archive.today 投诉事件的深度调查谷歌 GDPR 合规漏洞:Brave 揭露实时竞价广告系统的隐私数据广播机制
编写使用方法
Markdown 格式 · Ctrl+Enter 确定
0 字新建笔记
欢迎回来
登录你的墨穗笔记账户
忘记密码?
还没有账户?立即注册
创建账户
注册你的专属墨穗笔记
已有账户?去登录
找回密码
输入注册邮箱获取验证码
返回登录
请输入图片中的验证码以继续注册
加载中...
取消
新建收藏
手动添加你喜欢的内容
取消
编辑头像与昵称
上传新头像或修改你的显示昵称
支持 JPG/PNG,最大 2MB
取消

问题反馈

隐私提醒

取消
编辑工具
受控分享
为这篇笔记生成限时 / 带密码的临时链接
关闭