惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

H
Help Net Security
C
Cybersecurity and Infrastructure Security Agency CISA
S
Secure Thoughts
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Hacker News: Ask HN
Hacker News: Ask HN
Attack and Defense Labs
Attack and Defense Labs
N
News and Events Feed by Topic
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
A
Arctic Wolf
www.infosecurity-magazine.com
www.infosecurity-magazine.com
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
The GitHub Blog
The GitHub Blog
W
WeLiveSecurity
Simon Willison's Weblog
Simon Willison's Weblog
WordPress大学
WordPress大学
Y
Y Combinator Blog
Recent Commits to openclaw:main
Recent Commits to openclaw:main
Forbes - Security
Forbes - Security
NISL@THU
NISL@THU
博客园 - 聂微东
G
Google Developers Blog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Schneier on Security
Schneier on Security
V
Vulnerabilities – Threatpost
V
V2EX
I
Intezer
S
Schneier on Security
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
雷峰网
雷峰网
L
LangChain Blog
小众软件
小众软件
Hugging Face - Blog
Hugging Face - Blog
T
The Blog of Author Tim Ferriss
L
LINUX DO - 热门话题
P
Proofpoint News Feed
Microsoft Security Blog
Microsoft Security Blog
Project Zero
Project Zero
V
Visual Studio Blog
Engineering at Meta
Engineering at Meta
爱范儿
爱范儿
H
Hacker News: Front Page
B
Blog
T
Threatpost
Spread Privacy
Spread Privacy
H
Heimdal Security Blog
F
Fortinet All Blogs
TaoSecurity Blog
TaoSecurity Blog
T
Threat Research - Cisco Blogs
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
The Cloudflare Blog

少数派

派早报:Google 发布 Fitbit Air 等 - 少数派 「新人报到」確認需求,再開始 - 少数派 从 SOLO 独立开发者社区,我看到了越来越多开发者开始做自己的产品 - 少数派 我怎么管理那些"不常做,但总会忘"的生活事项 - 少数派 人形机器人量产元年,数据才是具身智能的“生死线” - 少数派 BuhoLaunchpad 高度还原 Mac 启动台:开发历程与思考 - 少数派 五年陪伴依然不舍,DIY 换壳后让罗技 MX Master 3 继续服役 - 少数派 新玩意 240|少数派的编辑们最近买了啥? - 少数派 一日一技|为什么你应该关闭 iOS 的键盘声音 - 少数派 我做了个插件和 Skills,一键提取任何网站的设计规范 Design.md - 少数派 住在三四线城市的你,该开始录播客了 - 少数派 甘南秘境,大白高国 - 少数派 AI的审美:谁让把我变成川内倫子 - 少数派 返工怎能不烦恼,打工人片单总有一部是你的「嘴替」 - 少数派 为了让「上厕所」更健康,我做了一个小工具 - 少数派 AI + Skill,能够让生成的文章去除 AI 味吗? - 少数派 新玩意|韶音OpenDots ONE 耳夹式耳机 - 少数派 《美满》| 在每一个春天的晚上相爱(362) - 少数派 新玩意|优篮子 PS01 MagSnap 磁吸支架 - 少数派 自我整合手记 | 我开始早睡了:用稳定规则,为自由托底 - 少数派 用龙虾(OpenClaw)两个多月,我最深的12个体会 - 少数派 听歌时间到,12 张你可能错过的 2025 华语乐坛好专辑 - 少数派 承诺能追吗 - 少数派 macOS 26启动台没了? 我做了个不一样的App启动器 - Keboard - 少数派 《四海为家的人》| INTJ对话INTJ(361) - 少数派 你发过的那些黑历史,是时候一次清干净了 - 少数派 新玩意:安安静静玩,越玩越专注:计客密码机 - 少数派 iPad 用户首次体验 Android 平板:vivo Pad6 Pro - 少数派 数据逻辑强 - 少数派 极北行+ | 一路向北,探访日本至北之地 | 001 - 少数派 万字剖析:千问App深度体验报告(2026) - 少数派 在2026年,如何真正防止别人抄袭你的作品 - 少数派 怎么用 50 块搭个 AI 语音助手?我踩了 3 天坑 - 少数派 YeeroAI:让 AI 对话真正成为知识管理的一部分 - 少数派 爬泰山 - 少数派 「旅图显影」 App 更新:这次,我们补上了一点「手感」 - 少数派 假期出门太折磨?我的 23 条经验帮你规划惬意旅行 - 少数派 工作流会变吗 - 少数派 Claude Opus 4.6 怎么用最省钱?我测了 5 种方案 - 少数派 GPT Image 2 让图文并茂不再稀罕 - 少数派 用户侧出发——什么是AI,我要不要学习? - 少数派 找片、转存、整理、播放一条龙!让你的付费网盘值回票价 - 少数派 欢迎试用!日课一问2.0插件 - 少数派 自己做的MDeditor,原本想购买 Typora 试了两次支付不成功,干脆自己做一个 - 少数派 vibe coding了一个 3MB 的小工具,让 ~/Downloads 彻底告别混乱 - 少数派 因为受不了 Mac 的风扇策略,我做了一个风扇控制工具 - 少数派 别只怪模型 - 少数派 Warp 终端的 AI 功能怎么用?我测了一周的体验 - 少数派 AI 写代码老是出 bug?这 5 个配置我后悔没早知道 - 少数派 「新玩意」苹果出相机可能就这样:Sigma BF + 45mm F2.8 DG Contemporary - 少数派 一个面向2030年的AI操作系统是什么样子的:浅谈cola这款有灵魂的Agent - 少数派 别只看写代码 - 少数派 每天解决10个问题,还是一口气攻坚解决400个? - 少数派 AI 交易机器人怎么搭?我用 Claude 跑了一周实盘 - 少数派 Maptoposter Online:把你爱的城市画成艺术海报 - 少数派 Function Calling 怎么用?我测了 3 个模型发现差距真大 - 少数派 Legend Talk:我做了个 AI 圆桌,让 160 位思想家围着你的问题转 - 少数派 如何找到自己的蓝方?在小县城寻找压力测试 - 少数派 语音输入与软件接口|2026年聊AI时,我们都聊些什么(上) - 少数派 混动已经卖爆,纯电又来补刀——钛7闪充版简直“不讲武德” - 少数派 本月玩什么|朋友收藏、识质存在、沙罗周期 - 少数派 为什么要每天坚持输出? - 少数派 Claude API 挂了好几个小时,你的项目有备用方案吗? - 少数派 Function Calling 没你想的复杂——我用它做了个有点用的工具 - 少数派 登录系统立即播放视频或者图片音乐的软件 - 少数派 我为什么创建 FlipHTML5 下载工具 - 少数派 残局没电?多品牌外设电量统一管理软件EasyBluetooth已支持RTSS游戏内显示以及AIDA64 - 少数派 前往通义路的路 - 少数派 太好看了,媲美Sun的个人导航页,NAS部署星云门户 - 少数派 乌黑嘴唇“一键检测”上线了 - 少数派 派早报:Claude AI 接入多个创意软件生态、FILCO 生产方接手品牌等 - 少数派 【更新】BearCLI、Claude 连接器与 MCP 服务器 - 少数派 记了上千条流水,还是看不懂财务?我做了一个让 AI 读懂账本的工作台 - 少数派 MINI R56 升级原厂 Sport 模式 - 少数派 新玩意 | 一棵柠檬树(仿真版) - 少数派 Momenta的“物理AI”野望,需迈过“含摩量”这道关 - 少数派 网页直接投屏控制手机!NAS一键部署PandaScrcpy,流畅丝滑可远程。 - 少数派 众测|邀你一同探索随身 AI 硬件入口 YoooClaw C·ONE - 少数派 2050大会:分享时间是真诚 参会记 - 少数派 iPad 赋能电影创作:国内首部宣纸手绘长片《燃比娃》的幕后故事 - 少数派 AI的审美:我用 8 个大模型给 100 张旅行照片打分 - 少数派 普通人如何破圈?去参加一个本地协会 - 少数派 把极空间的图标全换了,主题DIY全攻略打造你的专属NAS桌面 - 少数派 电子便签墙,帮你实现便签自由 - 少数派 我如何用三个 CLI 工具取代文档创建需求 - 少数派 原来真的有人可以玩一辈子 - 少数派 社区速递 139 | 派友热议三月买了啥、复古单反尼康 Df 体验 - 少数派 06 作品的赏析与评价 - 少数派 TDS REVIEW|索尼 WF-1000XM6 降噪真无线耳机体验 - 少数派 35.98万起售的第二代腾势D9,我看重的不是堆料,而是不凑合 - 少数派 鼠须管 Squirrel 皮肤配置指北 - 少数派 从watch ultra2换到redmi watch6 - 少数派 派早报:阿里巴巴发布视频生成模型 HappyHorse 1.0 等 - 少数派 别迷信1M - 少数派 家人们天塌了!网盘“大封杀”,多个渠道多条路,NAS部署PanHub - 少数派 AI与人勾心斗角!NAS一键部署AI狼人杀,假日休闲必备。 - 少数派 电商必备!Comfyui工作流批量生图插件,一次生成12张!支持Nano banana pro模型 - 少数派 Comfyui工作流配置Gpt-image-2模型教程,0.03/张 - 少数派 OpenClaw第三方APi怎么配置?可使用Gpt-image-2模型 - 少数派 会员社区话题精选 Ep. 103 - 少数派
如何在集群的负载均衡过程保留请求源IP - 少数派
2024-05-28 · via 少数派

引言

应用部署不一定总是简单的安装运行, 有时候还需要考虑网络的问题. 本文将介绍如何在k8s集群中使服务能获取到请求的源IP.

应用提供服务一般依赖输入信息, 输入信息如果不依赖五元组(源 IP, 源端口, 目的 IP, 目的端口, 协议), 那么该服务和网络耦合性低, 不需要关心网络细节.

因此, 对多数人来说都没有阅读本文的必要, 如果你对网络感兴趣, 或者希望拓宽一点视野, 可以继续阅读下文, 了解更多的服务场景.

本文基于 k8s v1.29.4, 文中部分叙述混用了 pod 和 endpoint, 本文场景下可以视为等价.

如果有错误, 欢迎指正, 我会及时更正.

我们首先明确源 IP 是什么, 当 A 向 B 发送请求, B 将请求转发给 C, 虽然 C 看到的 IP 协议的源 IP 是 B 的 IP, 但本文把A的IP看作源 IP.

主要有两类行为会导致源信息丢失:

  1. 网络地址转换(NAT), 目的是节省公网 IPv4, 负载均衡等. 将导致服务端看到的源 IP 是 NAT 设备的 IP, 而不是真实的源 IP.
  2. 代理(Proxy), 反向代理(RP, Reverse Proxy)和负载均衡(LB, Load Balancer)都属于这一类, 下文统称代理服务器. 这类代理服务会将请求转发给后端服务, 但是会将源 IP 替换为自己的 IP.
  • NAT 简单来说是以端口空间换IP空间, IPv4 地址有限, 一个 IP 地址可以映射 65535 个端口, 绝大多数时候这些端口没有用完, 因而可以多个子网 IP 共用一个公网 IP, 在端口上区分不同的服务. 其使用形式是: public IP:public port -> private IP_1:private port, 更多内容请自行参阅网络地址转换
  • 代理服务是为了隐藏或暴露, 代理服务会将请求转发给后端服务, 同时将源 IP 替换为自己的 IP, 以此来隐藏后端服务的真实 IP, 保护后端服务的安全. 代理服务的使用形式是: client IP -> proxy IP -> server IP, 更多内容请自行参阅代理

NAT代理服务器都非常常见, 多数服务都无法获得请求的源 IP.

这是常见的两类修改源 IP 的途径, 如有其它欢迎补充.

如何保留源 IP?

以下是一个 HTTP 请求的例子:

字段长度(字节)位偏移描述
IP 首部   
源 IP40-31发送方的 IP 地址
目的 IP432-63接收方的 IP 地址
TCP 首部   
源端口20-15发送端口号
目的端口216-31接收端口号
序列号432-63用于标识发送方发送的数据的字节流
确认号464-95如果设置了 ACK 标志,则为下一个期望收到的序列号
数据偏移496-103数据起始位置相对于 TCP 首部的字节数
保留4104-111保留字段,未使用,设置为 0
标志位2112-127各种控制标志,如 SYN、ACK、FIN 等
窗口大小2128-143接收方可以接收的数据量
检验和2144-159用于检测数据是否在传输过程中发生了错误
紧急指针2160-175发送方希望接收方尽快处理的紧急数据的位置
选项可变176-...可能包括时间戳、最大报文段长度等
HTTP 首部   
请求行可变...-...包括请求方法、URI 和 HTTP 版本
头部字段可变...-...包含各种头部字段,如 Host、User-Agent 等
空行2...-...用于分隔头部和主体部分
主体可变...-...可选的请求或响应正文

浏览以上 HTTP 请求结构, 可以发现, 有TCP选项,请求行, 头部字段,主体是可变的, 其中TCP选项空间有限, 一般不会用来传递源 IP, 请求行携带信息固定不能扩展, HTTP主体加密后不能修改, 只有HTTP 头部字段适合扩展传递源 IP.

HTTP header 中可以增加X-REAL-IP字段, 用来传递源 IP, 这个操作通常放在代理服务器上, 然后代理服务器会将请求发送给后端服务, 后端服务就可以通过这个字段获取到源 IP 信息.

注意, 需要保证代理服务器NAT设备之前, 这样才能获取到真实的请求的源 whoami. 我们可以在阿里云的产品中看到负载均衡器这个商品单独品类, 它在网络中的位置不同于普通的应用服务器.

K8S 操作指导

whoami项目为例进行部署.

创建 Deployment

首先创建服务:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: whoami-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: whoami
  template:
    metadata:
      labels:
        app: whoami
    spec:
      containers:
        - name: whoami
          image: docker.io/traefik/whoami:latest
          ports:
            - containerPort: 8080

这步会创建一个Deployment, 里面包含 3 个Pod, 每个 pod 包含一个容器, 该容器会运行whoami服务.

创建 Service

可以创建NodePort或者LoadBalancer类型的服务, 支持外部访问, 或者创建ClusterIP类型的服务, 仅支持集群内部访问, 再增加Ingress服务, 通过Ingress服务暴露外部访问.

NodePort既可以通过NodeIP:NodePort访问, 也可以通过Ingess服务访问, 方便测试, 本节使用NodePort服务.

apiVersion: v1
kind: Service
metadata:
  name: whoami-service
spec:
  type: NodePort
  selector:
    app: whoami
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080
      nodePort: 30002

创建服务后, 以curl whoami.example.com:30002访问, 可以看到返回的 IP 是NodeIP, 而不是请求的源 whoami.

请注意,这并不是正确的客户端 IP,它们是集群的内部 IP。这是所发生的事情:

  • 客户端发送数据包到 node2:nodePort
  • node2 使用它自己的 IP 地址替换数据包的源 IP 地址(SNAT)
  • node2 将数据包上的目标 IP 替换为 Pod IP
  • 数据包被路由到 node1,然后到端点
  • Pod 的回复被路由回 node2
  • Pod 的回复被发送回给客户端

用图表示:

配置 externalTrafficPolicy: Local

为避免这种情况,Kubernetes 有一个特性可以保留客户端源 IP。 如果将 service.spec.externalTrafficPolicy 设置为 Local, kube-proxy 只会将代理请求代理到本地端点,而不会将流量转发到其他节点。

apiVersion: v1
kind: Service
metadata:
  name: whoami-service
spec:
  type: NodePort
  externalTrafficPolicy: Local
  selector:
    app: whoami
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080
      nodePort: 30002

使用curl whoami.example.com:30002进行测试, 当whoami.example.com映射到集群多个 node 的 IP 时, 有一定比例的几率无法访问. 需要确认域名记录只含有 endpoint(pod)所在 node(节点)的 ip.

这个配置有其代价, 那就是失去了集群内的负载均衡能力, 客户端只有访问部署了 endpoint 的 node 才会得到响应.

访问路径限制

当客户端访问 Node 2 时, 不会有响应.

创建 Ingress

多数服务提供给用户时使用 http/https, https://ip:port的形式可能让用户感到陌生. 一般会使用Ingress将上文创建的NodePort服务负载到一个域名的 80/443 端口下.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: whoami-ingress
  namespace: default
spec:
  ingressClassName: external-lb-default
  rules:
    - host: whoami.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: whoami-service
                port:
                  number: 80

应用后, 使用curl whoami.example.com访问测试, 可以看到 ClientIP 总是 endpoint 所在节点上的Ingress Controller的 Pod IP.

root@client:~# curl whoami.example.com
...
RemoteAddr: 10.42.1.10:56482
...

root@worker:~# kubectl get -n ingress-nginx pod -o wide
NAME                                       READY   STATUS    RESTARTS   AGE    IP           NODE          NOMINATED NODE   READINESS GATES
ingress-nginx-controller-c8f499cfc-xdrg7   1/1     Running   0          3d2h   10.42.1.10   k3s-agent-1   <none>           <none>

使用Ingress反向代理NodePort服务, 也就是在 endpoint 前套了两层 service, 下图展示了二者区别.

graph LR
    A[Client] -->|whoami.example.com:80| B(Ingress)
    B -->|10.43.38.129:32123| C[Service]
    C -->|10.42.1.1:8080| D[Endpoint]
graph LR
    A[Client] -->|whoami.example.com:30001| B(Service)
    B -->|10.42.1.1:8080| C[Endpoint]

在路径 1 中, 外部访问 Ingress 时, 流量先到达的 endpoint 是Ingress Controller, 然后再到达 endpoint whoami.
Ingress Controller实质是一个LoadBalancer的服务,

kubectl -n ingress-nginx get svc

NAMESPACE   NAME             CLASS   HOSTS                       ADDRESS                                              PORTS   AGE
default     echoip-ingress   nginx   ip.example.com       172.16.0.57,2408:4005:3de:8500:4da1:169e:dc47:1707   80      18h
default     whoami-ingress   nginx   whoami.example.com   172.16.0.57,2408:4005:3de:8500:4da1:169e:dc47:1707   80      16h

因此, 可以通过将前文提到的externalTrafficPolicy设置到 Ingress Controller 中来保留源 IP.

同时还需要设置ingress-nginx-controllerconfigmap中的use-forwarded-headerstrue, 以便Ingress Controller能够识别X-Forwarded-ForX-REAL-IP字段.

apiVersion: v1
data:
  allow-snippet-annotations: "false"
  compute-full-forwarded-for: "true"
  use-forwarded-headers: "true"
  enable-real-ip: "true"
  forwarded-for-header: "X-Real-IP" # X-Real-IP or X-Forwarded-For
kind: ConfigMap
metadata:
  labels:
    app.kubernetes.io/component: controller
    app.kubernetes.io/instance: ingress-nginx
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
    app.kubernetes.io/version: 1.10.1
  name: ingress-nginx-controller
  namespace: ingress-nginx

NodePort服务与ingress-nginx-controller服务的区别主要在于, NodePort的后端通常不部署在每台 node 上, 而ingress-nginx-controller的后端通常部署在每台对外暴露的 node 上.

NodePort服务中设置externalTrafficPolicy会导致跨 node 的请求无响应不同, Ingress可以将请求先设置 HEADER 之后再进行代理转发, 实现了保留源 IP负载均衡的两种能力.

总结

  • 地址转换(NAT), 代理(Proxy),反向代理(Reverse Proxy), 负载均衡(Load Balance)会导致源 IP 丢失.
  • 为防止源 IP 丢失, 可以代理服务器转发时将真实 IP 设置在 HTTP 头部字段X-REAL-IP中, 通过代理服务传递. 如果使用多层代理, 则可以使用X-Forwarded-For字段, 该字段以的形式记录了源 IP 及代理路径的 IP list.
  • 集群NodePort服务设置externalTrafficPolicy: Local可以保留源 IP, 但会失去负载均衡能力.
  • ingress-nginx-controllerdaemonset形式部署在所有loadbalancer角色 node 上的前提下, 设置externalTrafficPolicy: Local可以保留源 IP, 且保留负载均衡能力.

参考