searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

一场由Host导致的困惑之旅

2025-06-17 09:18:19
1
0

最近开发一个新组件,需要开放接口给外部服务调用,自然需要使用openapi的接口鉴权的方式来控制访问权限。本以为按照以往的做法,能够很容易的实现鉴权功能。所以从一开始就对这个任务没在意,谁知却卡了很久了。

首先,因为需要鉴权的服务与鉴权服务分别位于不同的集群,所以先对访问的鉴权接口集群申请了IP白名单,然后配了deployment的hostAlias,再把原先的apisix自定义鉴权插件中把url改一下,以为就搞定了。然而事与愿违,发现apisix自定义鉴权插件请求鉴权接口时总是返回200状态的html文件,而不是预期的进入鉴权服务,鉴别接口的签名信息。
原apisix鉴权插件代码如下:
a69ed639309232a17594e4f33cd6e9d7.png

百思不得其解。总觉得apisix请求机制不同而导致请求鉴权接口没有到达鉴权服务那边,是因为域名问题,而导致请求数据包没有到达鉴权服务集群那边去。

因此,另辟蹊径,改用ingress的auth-url方式进行鉴权进入尝试

nginx.ingress.kubernetes.io/auth-response-headers: X-Auth-XXXXX
nginx.ingress.kubernetes.io/auth-url: "$AUTH_SERVER_URL"
nginx.ingress.kubernetes.io/configuration-snippet: | ****

但是发现还是调不通,请求鉴权接口出现 nginx 的500错误。经查看nginx ingress controller的日志发现错误日志如下:

[error] auth.server.com could not be resolved (3: Host not found), client: 172.16.7.0

意识到nginx ingress controller的无法识别这个域名,即使配置了hostAlias也不行。就像nginx配置中的upstream中的域名是无法使用/etc/hosts中配置的域名解析一样。于是,便在k8s中的coredns中加上host解析。至此使用ingress鉴权方式终于走通了。

自从ingress方式调通之后,就想着apisix应该也是理所当然的可以调通了。然而事与愿违,将ingress配置开启apisix-gateway接入之后,测试一下接口,却发现鉴权接口依然是返回那个不知从何而来的 200状态的html,顿时又陷入的深深的迷惘中......始终想不明白这个200状态的html来自哪里。

后来无意中把鉴权接口地址换成了百度或者其他常见的域名时候,发现居然与浏览器访问页面不同。因此开始怀疑自定义的apisix鉴权插件中使用的resty.http库有问题。于是便开始捋起lua-resty-http源码来,其中request_uri部分相关源码如下:

db692998a4a521f3378265b110d6edf8.png

其先使用connect方法建tcp连接,然后再发送http请求。于是判定出问题的地址应该就是在发送请求时的这个request方法中。此时我将鉴权接口的url中的域名部分换成其IP地址,然后看到其访问的response,瞬时顿悟了,这返回与上面使用域名的url访问是一样的内容。这是由于一个 IP 地址同时提供多个域名服务时,使用 IP 地址无法调用到具体的某域名服务,缺少Host信息的症状!

于是,立刻动手,将apisix鉴权插件改成使用用apisix自带的forward-auth插件后,一切都正常了。

翻开 lua-resty-http 插件源码发现,当 header 中没有 Host 信息时,其会使用 socket 连接前通过域名解释出来的 IP 地址作为 Host 值,此时的 Host 已经不是请求鉴权接口那个域名了:

f4417d259c202f4b44dc8e5674ac6b1b.png

0条评论
0 / 1000
杜****中
5文章数
0粉丝数
杜****中
5 文章 | 0 粉丝
原创

一场由Host导致的困惑之旅

2025-06-17 09:18:19
1
0

最近开发一个新组件,需要开放接口给外部服务调用,自然需要使用openapi的接口鉴权的方式来控制访问权限。本以为按照以往的做法,能够很容易的实现鉴权功能。所以从一开始就对这个任务没在意,谁知却卡了很久了。

首先,因为需要鉴权的服务与鉴权服务分别位于不同的集群,所以先对访问的鉴权接口集群申请了IP白名单,然后配了deployment的hostAlias,再把原先的apisix自定义鉴权插件中把url改一下,以为就搞定了。然而事与愿违,发现apisix自定义鉴权插件请求鉴权接口时总是返回200状态的html文件,而不是预期的进入鉴权服务,鉴别接口的签名信息。
原apisix鉴权插件代码如下:
a69ed639309232a17594e4f33cd6e9d7.png

百思不得其解。总觉得apisix请求机制不同而导致请求鉴权接口没有到达鉴权服务那边,是因为域名问题,而导致请求数据包没有到达鉴权服务集群那边去。

因此,另辟蹊径,改用ingress的auth-url方式进行鉴权进入尝试

nginx.ingress.kubernetes.io/auth-response-headers: X-Auth-XXXXX
nginx.ingress.kubernetes.io/auth-url: "$AUTH_SERVER_URL"
nginx.ingress.kubernetes.io/configuration-snippet: | ****

但是发现还是调不通,请求鉴权接口出现 nginx 的500错误。经查看nginx ingress controller的日志发现错误日志如下:

[error] auth.server.com could not be resolved (3: Host not found), client: 172.16.7.0

意识到nginx ingress controller的无法识别这个域名,即使配置了hostAlias也不行。就像nginx配置中的upstream中的域名是无法使用/etc/hosts中配置的域名解析一样。于是,便在k8s中的coredns中加上host解析。至此使用ingress鉴权方式终于走通了。

自从ingress方式调通之后,就想着apisix应该也是理所当然的可以调通了。然而事与愿违,将ingress配置开启apisix-gateway接入之后,测试一下接口,却发现鉴权接口依然是返回那个不知从何而来的 200状态的html,顿时又陷入的深深的迷惘中......始终想不明白这个200状态的html来自哪里。

后来无意中把鉴权接口地址换成了百度或者其他常见的域名时候,发现居然与浏览器访问页面不同。因此开始怀疑自定义的apisix鉴权插件中使用的resty.http库有问题。于是便开始捋起lua-resty-http源码来,其中request_uri部分相关源码如下:

db692998a4a521f3378265b110d6edf8.png

其先使用connect方法建tcp连接,然后再发送http请求。于是判定出问题的地址应该就是在发送请求时的这个request方法中。此时我将鉴权接口的url中的域名部分换成其IP地址,然后看到其访问的response,瞬时顿悟了,这返回与上面使用域名的url访问是一样的内容。这是由于一个 IP 地址同时提供多个域名服务时,使用 IP 地址无法调用到具体的某域名服务,缺少Host信息的症状!

于是,立刻动手,将apisix鉴权插件改成使用用apisix自带的forward-auth插件后,一切都正常了。

翻开 lua-resty-http 插件源码发现,当 header 中没有 Host 信息时,其会使用 socket 连接前通过域名解释出来的 IP 地址作为 Host 值,此时的 Host 已经不是请求鉴权接口那个域名了:

f4417d259c202f4b44dc8e5674ac6b1b.png

文章来自个人专栏
文章 | 订阅
0条评论
0 / 1000
请输入你的评论
0
0