百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

Kong系列(三)——Kong插件「IP Restriction」使用

nanshan 2024-10-22 12:57 10 浏览 0 评论

Kong plugin 说明

Kong的官网中可以看到目前针对不同的需求提供了很多的插件,大部分都是开源版本,只有少部分是企业版

Kong的插件本身就是基于NGINX的一些属性,来做一些扩展,比如通过IP进行限流,通过IP来限制黑白名单等等,在实际业务中可能需要用到的扩展

Plugin IP Restriction 简单说明

-- E:\work\projects\kong\kong\plugins\ip-restriction\handler.lua
function IpRestrictionHandler:access(conf)
 IpRestrictionHandler.super.access(self)
 local block = false
 local binary_remote_addr = ngx.var.binary_remote_addr

 if not binary_remote_addr then
 return responses.send_HTTP_FORBIDDEN("Cannot identify the client IP address, unix domain sockets are not supported.")
 end

 if conf.blacklist and #conf.blacklist > 0 then
 block = iputils.binip_in_cidrs(binary_remote_addr, cidr_cache(conf.blacklist))
 end

 if conf.whitelist and #conf.whitelist > 0 then
 block = not iputils.binip_in_cidrs(binary_remote_addr, cidr_cache(conf.whitelist))
 end

 if block then
 return responses.send_HTTP_FORBIDDEN("Your IP address is not allowed")
 end
end

配置

配置插件的方式比较简单,插件可以设置到service上,可以设置到route上,0.13之前的也可以设置到api上,还有一些其他的组件也可以设置

我是设置到route上的,如果大家有其他需求可以到官网上查看文档

  • 添加
curl -X POST http://localhost:8001/routes/b01067c3-2537-45c8-be41-a80082c8bff3/plugins \
--data "name=ip-restriction" \
--data "config.whitelist=172.17.83.176, 172.17.83.177"

给ID为b01067c3-2537-45c8-be41-a80082c8bff3增加ip-restriction插件

  • 修改
curl -X PATCH http://localhost:8001/routes/b01067c3-2537-45c8-be41-a80082c8bff3/plugins \
--data "name=ip-restriction" \
--data "config.whitelist=172.17.83.177"
  • 查看
curl -i --url http://localhost:8001/plugins

# 结果
{
 "total": 1,
 "data": [{
 "created_at": 1531446541000,
 "config": {
 "whitelist": ["172.17.83.177"]
 },
 "id": "ed6d0fb3-1dd6-4bc8-8712-75d338c2bda9",
 "name": "ip-restriction",
 "enabled": true,
 "route_id": "b01067c3-2537-45c8-be41-a80082c8bff3"
 }]
}
  • 删除
curl -X DELETE --url http://localhost:8001/plugins/bf95c7e8-bcd2-460a-a18b-bd1a309d7578/

想象中是配置完成之后,应该立马就可以使用了。

然后我分别从两个服务器上进行了测试,期望的结果应该是除了172.17.83.177这台服务器之外,应该都不可以用。

但是发起结果其实并不是这个样子,而是所有的都可以继续访问。

排查发现,我的Kong节点是部署在NGINX之后,通过NGINX反向代理到Kong节点的,我的NGINX反向代理节点部署在172.17.83.177。

所以说最终无论从哪儿访问,而Kong看到的节点就是177,所以最终发现无论从哪台服务器访问都是可以的,这显然是不符合我们的预期,经过查找资料找到解决方案,我们下节就重点描述此部分。

复杂配置

解决方案

首先说一下上节中提到的问题,读IP Restriction源码可以发现,他是用ngx.var.binary_remote_addr来识别出客户端IP地址的,我们从NGINX可以了解到,这个地址通过代理之后,就已经发生了变化,这就是导致我们获得的地址都是我们代理的地址,所以就失去了原本的意义。

所以我们显然要做的就是将ngx.var.binary_remote_addr变为客户端的地址就能解决问题。

通过查找资料发现kong的版本中的变化,已经如何获得客户端真实的IP地址。

在0.11版本之后,Kong会设置X-Forwarded-For头,所以在这里会记录下所有的请求信息,所以我们也要在代理中也进行设置X-Forwarded-For头,这样才能保证Kong中可以得到最原始的信息,所以解决这个问题的方法就是依靠NGINX 的ngx_http_realip_module,该模块已经在Kong的官方发行包中。此模块X-Forwarded-For根据我们配置的规则正确解析请求头。

Kong公开的配置文件,我们可以看到(trusted_ips,real_ip_header 和real_ip_recursive)属性,它们抽象出NGINX模块的同名指令,通过设置这些属性,我们就可以得到客户端的真实地址

ngx_http_realip_module会更新NGINX的$remote_addr变量来包含客户端IP。

IP限制插件使用ngx.var.binary_remote_addr,该变量也由realip模块更新。

在0.11之前,X-Forwarded-For来自任何来源的Kong请求头(默认情况下)。

从0.11开始,Kong默认不会信任来自任何来源的请求头,所以需要通过我们的设置来完成信任。

在我们使用反向代理或者负载均衡时,需要设置Kong提供的属性(trusted_ips,real_ip_header 和real_ip_recursive),以及我们自己的NGINX反向代理或者负载均衡时要设置的请求头[X-Forwarded-For],下面就分成两部分设置来解决此问题。

NGINX 反向代理配置

这一步比较简单,就是要将客户端的IP地址收集到请求头X-Forwarded-For中,不管有多少层代理,这个请求头中会记录整个请求的声明周期,就是讲每次的IP地址都放在X-Forwarded-For中,然后使用逗号进行分隔,所以最终Kong只需要在取第一项即可,重点的配置如下:

location ~ /(\w+) {
 proxy_set_header Host $http_host;
 proxy_redirect off;
 proxy_set_header X-Real-IP $remote_addr;
 proxy_set_header X-Scheme $scheme;
 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
 proxy_pass http://172.17.83.176:8000;
 expires -1;
}

重点就是 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

通过docker启动kong命令设置nginx-kong.conf

  • 启动命令
docker run -d --name kong \
-e "KONG_TRUSTED_IPS=0.0.0.0/0,::/0" \
-e "KONG_REAL_IP_HEADER=X-Forwarded-For" \
-e "KONG_DATABASE=postgres" \
-e "KONG_PG_HOST=192.168.1.94" \
-e "KONG_CASSANDRA_CONTACT_POINTS=kong-database" \
-e "KONG_PROXY_ACCESS_LOG=logs/proxy_access.log" \
-e "KONG_ADMIN_ACCESS_LOG=logs/admin_access.log" \
-e "KONG_PROXY_ERROR_LOG=logs/proxy_error.log" \
-e "KONG_ADMIN_ERROR_LOG=logs/admin_error.log" \
-e "KONG_ADMIN_LISTEN=0.0.0.0:8001, 0.0.0.0:8444 ssl" \
-p 8000:8000 \
-p 8443:8443 \
-p 8001:8001 \
-p 8444:8444 \
kong:latest

划重点

-e “KONG_TRUSTED_IPS=0.0.0.0/0,::/0”
-e “KONG_REAL_IP_HEADER=X-Forwarded-For”

trusted_ips和real_ip_header是kong需要的一些参数,这里有些参数最终会映射到nginx-kong.conf文件中,可以从kong的配置文件中可以看到其类型

trusted_ips表示信任的地址,如果是所有的地址都信任,可以配置为0.0.0.0/0,::/0

real_ip_header表示的是

-- E:\work\projects\kong\kong\templates\kong_defaults.lua
return [[
prefix = /usr/local/kong/
log_level = notice
proxy_access_log = logs/access.log
proxy_error_log = logs/error.log
admin_access_log = logs/admin_access.log
admin_error_log = logs/error.log
plugins = bundled
custom_plugins = NONE
anonymous_reports = on

proxy_listen = 0.0.0.0:8000, 0.0.0.0:8443 ssl
admin_listen = 127.0.0.1:8001, 127.0.0.1:8444 ssl
nginx_user = nobody nobody
nginx_worker_processes = auto
nginx_optimizations = on
nginx_daemon = on
mem_cache_size = 128m
ssl_cert = NONE
ssl_cert_key = NONE
client_ssl = off
client_ssl_cert = NONE
client_ssl_cert_key = NONE
ssl_cipher_suite = modern
ssl_ciphers = ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256
admin_ssl_cert = NONE
admin_ssl_cert_key = NONE
upstream_keepalive = 60
headers = server_tokens, latency_tokens
trusted_ips = NONE
real_ip_header = X-Real-IP
real_ip_recursive = off
client_max_body_size = 0
client_body_buffer_size = 8k
error_default_type = text/plain

database = postgres
pg_host = 127.0.0.1
pg_port = 5432
pg_database = kong
pg_user = kong
pg_password = NONE
pg_ssl = off
pg_ssl_verify = off
cassandra_contact_points = 127.0.0.1
cassandra_port = 9042
cassandra_keyspace = kong
cassandra_timeout = 5000
cassandra_ssl = off
cassandra_ssl_verify = off
cassandra_username = kong
cassandra_password = NONE
cassandra_consistency = ONE
cassandra_lb_policy = RoundRobin
cassandra_local_datacenter = NONE
cassandra_repl_strategy = SimpleStrategy
cassandra_repl_factor = 1
cassandra_data_centers = dc1:2,dc2:3
cassandra_schema_consensus_timeout = 10000

db_update_frequency = 5
db_update_propagation = 0
db_cache_ttl = 0
db_resurrect_ttl = 30

dns_resolver = NONE
dns_hostsfile = /etc/hosts
dns_order = LAST,SRV,A,CNAME
dns_stale_ttl = 4
dns_not_found_ttl = 30
dns_error_ttl = 1
dns_no_sync = off

lua_socket_pool_size = 30
lua_ssl_trusted_certificate = NONE
lua_ssl_verify_depth = 1
lua_package_path = ./?.lua;./?/init.lua;
lua_package_cpath = NONE
]]

注意:

这里面的参数,都可以在使用docker启动时,通过-e的方式传递进去,前提是要在这个参数的名字之前加上前缀KONG_*,并且全部是大写

  • nginx-kong.conf

我们使用docker启动后,nginx-kong.conf的内容已经设置为我们命令中指定的参数

charset UTF-8;

error_log syslog:server=kong-hf.mashape.com:61828 error;

error_log logs/proxy_error.log notice;


client_max_body_size 0;
proxy_ssl_server_name on;
underscores_in_headers on;

lua_package_path './?.lua;./?/init.lua;;;';
lua_package_cpath ';;';
lua_socket_pool_size 30;
lua_max_running_timers 4096;
lua_max_pending_timers 16384;
lua_shared_dict kong 5m;
lua_shared_dict kong_cache 128m;
lua_shared_dict kong_db_cache_miss 12m;
lua_shared_dict kong_process_events 5m;
lua_shared_dict kong_cluster_events 5m;
lua_shared_dict kong_healthchecks 5m;
lua_shared_dict kong_rate_limiting_counters 12m;
lua_socket_log_errors off;

init_by_lua_block {
 kong = require 'kong'
 kong.init()
}

init_worker_by_lua_block {
 kong.init_worker()
}


upstream kong_upstream {
 server 0.0.0.1;
 balancer_by_lua_block {
 kong.balancer()
 }
 keepalive 60;
}

server {
 server_name kong;
 listen 0.0.0.0:8000;
 listen 0.0.0.0:8443 ssl;
 error_page 400 404 408 411 412 413 414 417 494 /kong_error_handler;
 error_page 500 502 503 504 /kong_error_handler;

 access_log logs/proxy_access.log;
 error_log logs/proxy_error.log notice;

 client_body_buffer_size 8k;

 ssl_certificate /usr/local/kong/ssl/kong-default.crt;
 ssl_certificate_key /usr/local/kong/ssl/kong-default.key;
 ssl_protocols TLSv1.1 TLSv1.2;
 ssl_certificate_by_lua_block {
 kong.ssl_certificate()
 }

 ssl_session_cache shared:SSL:10m;
 ssl_session_timeout 10m;
 ssl_prefer_server_ciphers on;
 ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA3


 real_ip_header X-Forwarded-For;
 real_ip_recursive on;
 set_real_ip_from 0.0.0.0/0; 
 set_real_ip_from ::/0;

 location / {
 set $upstream_host '';
 set $upstream_upgrade '';
 set $upstream_connection '';
 set $upstream_scheme '';
 set $upstream_uri '';
 set $upstream_x_forwarded_for '';
 set $upstream_x_forwarded_proto '';
 set $upstream_x_forwarded_host '';
 set $upstream_x_forwarded_port '';

 rewrite_by_lua_block { 
 kong.rewrite() 
 } 

 access_by_lua_block { 
 kong.access() 
 } 

 proxy_http_version 1.1;
 proxy_set_header Host $upstream_host;
 proxy_set_header Upgrade $upstream_upgrade;
 proxy_set_header Connection $upstream_connection;
 proxy_set_header X-Forwarded-For $upstream_x_forwarded_for;
 proxy_set_header X-Forwarded-Proto $upstream_x_forwarded_proto;
 proxy_set_header X-Forwarded-Host $upstream_x_forwarded_host;
 proxy_set_header X-Forwarded-Port $upstream_x_forwarded_port;
 proxy_set_header X-Real-IP $remote_addr;
 proxy_pass_header Server;
 proxy_pass_header Date;
 proxy_ssl_name $upstream_host;
 proxy_pass $upstream_scheme://kong_upstream$upstream_uri;

 header_filter_by_lua_block {
 kong.header_filter()
 } 

 body_filter_by_lua_block {
 kong.body_filter()
 } 

 log_by_lua_block { 
 kong.log() 
 } 
 }

 location = /kong_error_handler { 
 internal;
 content_by_lua_block { 
 kong.handle_error()
 } 
 } 
} 

server { 
 server_name kong_admin;
 listen 0.0.0.0:8001;
 listen 0.0.0.0:8444 ssl; 

 access_log logs/admin_access.log;
 error_log logs/admin_error.log notice; 

 client_max_body_size 10m;
 client_body_buffer_size 10m; 
 ssl_certificate /usr/local/kong/ssl/admin-kong-default.crt;
 ssl_certificate_key /usr/local/kong/ssl/admin-kong-default.key;
 ssl_protocols TLSv1.1 TLSv1.2; 

 ssl_session_cache shared:SSL:10m; 
 ssl_session_timeout 10m; 
 ssl_prefer_server_ciphers on; 
 ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA3

 location / { 
 default_type application/json; 
 content_by_lua_block { 
 kong.serve_admin_api() 
 } 
 } 

 location /nginx_status { 
 internal; 
 access_log off; 
 stub_status; 
 } 

 location /robots.txt { 
 return 200 'User-agent: *\nDisallow: /'; 
 } 
} 

相关推荐

F5负载均衡器如何通过irules实现应用的灵活转发?

F5是非常强大的商业负载均衡器。除了处理性能强劲,以及高稳定性之外,F5还可以通过irules编写强大灵活的转发规则,实现web业务的灵活应用。irules是基于TCL语法的,每个iRules必须包含...

映射域名到NAS

前面介绍已经将域名映射到家庭路由器上,现在只需要在路由器上设置一下端口转发即可。假设NAS在内网的IP是192.168.1.100,NAS管理端口2000.你的域名是www.xxx.com,配置外部端...

转发(Forward)和重定向(Redirect)的区别

转发是服务器行为,重定向是客户端行为。转发(Forward)通过RequestDispatcher对象的forward(HttpServletRequestrequest,HttpServletRe...

SpringBoot应用中使用拦截器实现路由转发

1、背景项目中有一个SpringBoot开发的微服务,经过业务多年的演进,代码已经累积到令人恐怖的规模,亟需重构,将之拆解成多个微服务。该微服务的接口庞大,调用关系非常复杂,且实施重构的人员大部分不是...

公司想搭建个网站,网站如何进行域名解析?

域名解析是将域名指向网站空间IP,让人们通过注册的域名可以方便地访问到网站的一种服务。IP地址是网络上标识站点的数字地址,为方便记忆,采用域名来代替IP地址标识站点地址。域名解析就是域名到IP地址的转...

域名和IP地址什么关系?如何通过域名解析IP?

一般情况下,访客通过域名和IP地址都能访问到网站,那么两者之间有什么关系吗?本文中科三方针对域名和IP地址的关系和区别,以及如何实现域名与IP的绑定做下介绍。域名与IP地址之间的关系IP地址是计算机的...

分享网站域名301重定向的知识

网站域名做301重定向操作时,一般需要由专业的技术来协助完成,如果用户自己在维护,可以按照相应的说明进行操作。好了,下面说说重点,域名301重定向的操作步骤。首先,根据HTTP协议,在客户端向服务器发...

NAS外网到底安全吗?一文看懂HTTP/HTTPS和SSL证书

本内容来源于@什么值得买APP,观点仅代表作者本人|作者:可爱的小cherry搭好了NAS,但是不懂做好网络加密,那么隐私泄露也会随时发生!大家好,这里是Cherry,喜爱折腾、玩数码,热衷于分享数...

ForwardEmail免费、开源、加密的邮件转发服务

ForwardEmail是一款免费、加密和开源的邮件转发服务,设置简单只需4步即可正常使用,通过测试来看也要比ImprovMX好得多,转发近乎秒到且未进入垃圾箱(仅以Mailbox.org发送、Out...

使用CloudFlare进行域名重定向

当网站变更域名的时候,经常会使用域名重定向的方式,将老域名指向到新域名,这通常叫做:URL转发(URLFORWARDING),善于使用URL转发,对SEO来说非常有用,因为用这种方式能明确告知搜索引...

要将端口5002和5003通过Nginx代理到一个域名上的操作笔记

要将端口5002和5003通过Nginx代理到域名www.4rvi.cn的不同路径下,请按照以下步骤配置Nginx:步骤说明创建或编辑Nginx配置文件通常配置文件位于/etc/nginx/sites...

SEO浅谈:网站域名重定向的三种方式

在大多数情况下,我们输入网站访问网站的时候,很难发现www.***.com和***.com的区别,因为一般的网站主,都会把这两个域名指向到同一网站。但是对于网站运营和优化来说,www.***.com和...

花生壳出现诊断域名与转发服务器ip不一致的解决办法

出现诊断域名与转发服务器ip不一致您可以:1、更改客户端所处主机的drs为223.5.5.5备用dns为119.29.29.29;2、在windows上进入命令提示符输入ipconfig/flush...

涨知识了!带你认识什么是域名

1、什么是域名从技术角度来看,域名是在Internet上解决IP地址对应的一种方法。一个完整的域名由两个或两个以上部分组成,各部分之间用英文的句号“.”来分隔。如“abc.com”。其中“com”称...

域名被跳转到其他网站是怎么回事

当你输入域名时被跳转到另一个网站,这可能是由几种原因造成的:一、域名可能配置了域名转发服务。无论何时有人访问域名,比如.com、.top等,都会自动重定向到另一个指定的URL,这通常是在域名注册商设...

取消回复欢迎 发表评论: