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

推荐订阅源

aimingoo的专栏
aimingoo的专栏
S
Securelist
博客园 - Franky
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
IT之家
IT之家
GbyAI
GbyAI
Microsoft Azure Blog
Microsoft Azure Blog
The Cloudflare Blog
云风的 BLOG
云风的 BLOG
N
News and Events Feed by Topic
AI
AI
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Schneier on Security
Schneier on Security
Attack and Defense Labs
Attack and Defense Labs
Vercel News
Vercel News
腾讯CDC
Google DeepMind News
Google DeepMind News
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
M
MIT News - Artificial intelligence
WordPress大学
WordPress大学
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
N
Netflix TechBlog - Medium
量子位
S
Schneier on Security
Hacker News: Ask HN
Hacker News: Ask HN
Cyberwarzone
Cyberwarzone
S
Security Affairs
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
N
News and Events Feed by Topic
T
Tenable Blog
PCI Perspectives
PCI Perspectives
MyScale Blog
MyScale Blog
L
Lohrmann on Cybersecurity
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
C
Cyber Attacks, Cyber Crime and Cyber Security
W
WeLiveSecurity
N
News | PayPal Newsroom
P
Proofpoint News Feed
O
OpenAI News
C
CERT Recently Published Vulnerability Notes
B
Blog
Cisco Talos Blog
Cisco Talos Blog
Microsoft Security Blog
Microsoft Security Blog
V
Visual Studio Blog
MongoDB | Blog
MongoDB | Blog
大猫的无限游戏
大猫的无限游戏
A
Arctic Wolf
Y
Y Combinator Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Spread Privacy
Spread Privacy

PixelNest

会议是效率的杀手 国庆出游记录 对居家办公的一些想法 2022 春节 《搏击俱乐部》的结局 纪念 PAI 头一回达到 100 卡片笔记法 《刑法学讲义》的部分摘录 迁移博客 《UNIX 传奇》摘录 就地过年 一点记录:docker-compose 编排不同项目间的网络 近期读的几本书 办新身份证 git 获取其他分支的单个文件或目录 我的高考成绩 推荐 2020 年上半年的 8 部影视作品 ChromeOS 开发者模式 终于下单了《守望者》 联通来电管家服务 一些实用的 bash 代码片段 关于 鸟枪换炮 《架构整洁之道》摘录 惨淡的星球大战 旧笔记本电脑 if...then... 命令行检测 SSL 证书过期时间 《程序员的职业素养》读书笔记 2019 国庆假期 在 Ubuntu 里按空格键预览 《基本穿搭》笔记 我在 Ubuntu 里安装的一些软件 让人郁闷的英语学习过程 色彩理论基础 向百度主动推送网站链接 两部电视剧 《历史的教训》摘录 新工具 备案了 apiDoc 基础语法 《代码整洁之道》摘录 BBC 纪录片 《逻辑的乐趣》 读不下去的《原则》 蓝牙鼠标唤醒休眠的 Ubuntu Google 发布会 2018 国庆假期 开发者的时间追踪和统计 使用 curl 发送 POST 请求的几种方式 《重来 2》读书笔记 Linux 和 MacOS 命令行转换图片用法整理 《Go 语言实战》笔记 Win10 微软拼音添加小鹤双拼以及其他配置 针对不同场景临时禁用 eslint 规则的方法 《好妈妈胜过好老师》读书笔记 配置 Win10 Linux 子系统作为开发环境 又读完一本尤·奈斯博的小说 近期写 Go 的一点语法碎片整理 ffmpeg 合并 MP4 M4A 文件 睡前看手机的大问题 《局外人》读书笔记 菊次郎与佐纪 读书笔记 3 菊次郎与佐纪 读书笔记 2 菊次郎与佐纪 读书笔记 1 豆瓣图片服务器防盗链 《如何有效阅读一本书》读书笔记 - 3 《如何有效阅读一本书》读书笔记 - 2 《如何有效阅读一本书》读书笔记 - 1 Vim iskeyword 济南 图个乐 开始看不懂《西部世界》了 剧透 听到几个好故事 过周末 相亲 让人失望的 Apple 悬疑故事 AI 记忆 世纪三部曲 上帝的梦
Koa 获取客户端 IP
2019-03-20 · via PixelNest

这篇文章记录在 Koa 应用里获取真实客户端 IP 的方法、X-Forwarded-For 等 HTTP 头部字段的含义,以及相关的 Nginx 配置。

ctx.request.ip

在 Koa 里获取客户端 IP 非常容易,简单来说,ctx.request.ip 就是客户端 IP。哪个 IP 请求过来的,哪个 IP 就是客户端 IP。

但是在生产环境服务器上,Koa 的前端往往还有一个反向代理服务器,比如 Nginx。这时候 ctx.request.ip 的值就是 Nginx 所在的 IP,往往就是本地地址 127.0.0.1。那么这时要怎么获取到客户端的真实 IP?

Koa 的文档里对 ctx.request.ip 的描述是这样的:

Request remote address. Supports X-Forwarded-For when app.proxy is true.

这句文档的后半句针对的就是上面提到的问题,也指明了方向。

下面是答案,做两件事情就可以了 :

  1. 在 Nginx 反向代理配置 proxy_pass 的部分添加这样一行。 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  2. 在 Koa 应用里设置 app.proxytrue

这样,从 ctx.request.ip 拿到的就是客户端的真实 IP,而不是(反向)代理的 IP。

Nginx 通过设置 X-Forwarded-For 告诉 Koa 它为谁做代理。如果 Koa 中没有配置 app.proxy = true,Koa 会忽略 Nginx 在 HTTP 请求头部添加的 X-Forwarded-For 字段,所以要设置app.proxytrue

X-Forwarded-For

可以从 X-Forwarded-For 的名称里猜到,这个 HTTP 请求头部字段的含义是告诉 HTTP 的请求接收方「我在转发的谁的请求」,它并不只是包含最原始的客户端 IP,在维基百科的描述如下:

这一HTTP头一般格式如下:

X-Forwarded-For: client1, proxy1, proxy2

其中的值通过一个 逗号+空格 把多个IP地址区分开, 最左边(client1)是最原始客户端的IP地址, 代理服务器每成功收到一个请求,就把请求来源IP地址添加到右边。 在上面这个例子中,这个请求成功通过了三台代理服务器:proxy1, proxy2 及 proxy3。请求由client1发出,到达了proxy3(proxy3可能是请求的终点)。请求刚从client1中发出时,XFF是空的,请求被发往proxy1;通过proxy1的时候,client1被添加到XFF中,之后请求被发往proxy2;通过proxy2的时候,proxy1被添加到XFF中,之后请求被发往proxy3;通过proxy3时,proxy2被添加到XFF中,之后请求的的去向不明,如果proxy3不是请求终点,请求会被继续转发。

实际的生产环境中,极有可能并不是用户(客户端)-> 服务器 Nginx -> 服务器 Koa 这样简单的三个点,在用户和服务器之前,可能还有其他代理,比如 CDN,负载均衡,或许还有用户自己用的代理服务。通过上述方法,还是可以拿到最原始的真实客户端 IP,当然,这需要整个请求链条上各个点都遵照 X-Forwarded-For 头部的用法。

每个点把请求代理给下一个点时,都需要带上 X-Forwarded-For 头部字段,具体的做法是要把收到请求中的 X-Forwarded-For 拿过来,再给这个字段追加发起这个请求的节点 IP。

上面提到的 Nginx 配置 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 就是这么做的,在 Nginx 文档里有对 $proxy_add_x_forwarded_for 这个变量的说明:

$proxy_add_x_forwarded_for

the “X-Forwarded-For” client request header field with the $remote_addr variable appended to it, separated by a comma. If the “X-Forwarded-For” field is not present in the client request header, the $proxy_add_x_forwarded_for variable is equal to the $remote_addr variable.

$proxy_add_x_forwarded_for 是指请求过来的 HTTP 中 X-Forwarded-For 头部再追加上请求方自身的 IP($remote_addr)。

如果 Nginx 收到的请求中的 X-Forwarded-For 是空的,有可能这个 Nginx 是最靠近真实用户的节点,也有可能是前一节代理节点丢掉了 X-Forwarded-For 字段,这时 Nginx 转发请求时添加的 X-Forwarded-For 就是 $remote_addr 变量,即请求发起方的 IP。

ctx.request.ips

再回到 Koa。当 Koa 收到的请求中 X-Forwarded-For 包含多个 IP 时,也就是 X-Forwarded-For: client1, proxy1, proxy2 这样的形式,可以通过 ctx.request.ips 获取到这个 IP 列表,值为 [client1, proxy1, proxy2],ctx.request.ips[0]是真实客户端 IP(与ctx.request.ip是同一个 IP,即client1`),数组后面的各个 IP 是各级代理的 IP 地址。