龙空技术网

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

战渣渣 96

前言:

现时朋友们对“nginx大小写不敏感”大概比较注意,大家都想要了解一些“nginx大小写不敏感”的相关内容。那么小编在网络上网罗了一些有关“nginx大小写不敏感””的相关知识,希望小伙伴们能喜欢,咱们一起来了解一下吧!

Kong plugin 说明

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

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

Plugin IP Restriction 简单说明

-- E:\work\projects\kong\kong\plugins\ip-restriction\handler.luafunction 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") endend
配置

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

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

添加

curl -X POST  \--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  \--data "name=ip-restriction" \--data "config.whitelist=172.17.83.177"
查看
curl -i --url  结果{ "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 

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

然后我分别从两个服务器上进行了测试,期望的结果应该是除了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 ; 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.luareturn [[prefix = /usr/local/kong/log_level = noticeproxy_access_log = logs/access.logproxy_error_log = logs/error.logadmin_access_log = logs/admin_access.logadmin_error_log = logs/error.logplugins = bundledcustom_plugins = NONEanonymous_reports = onproxy_listen = 0.0.0.0:8000, 0.0.0.0:8443 ssladmin_listen = 127.0.0.1:8001, 127.0.0.1:8444 sslnginx_user = nobody nobodynginx_worker_processes = autonginx_optimizations = onnginx_daemon = onmem_cache_size = 128mssl_cert = NONEssl_cert_key = NONEclient_ssl = offclient_ssl_cert = NONEclient_ssl_cert_key = NONEssl_cipher_suite = modernssl_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-SHA256admin_ssl_cert = NONEadmin_ssl_cert_key = NONEupstream_keepalive = 60headers = server_tokens, latency_tokenstrusted_ips = NONEreal_ip_header = X-Real-IPreal_ip_recursive = offclient_max_body_size = 0client_body_buffer_size = 8kerror_default_type = text/plaindatabase = postgrespg_host = 127.0.0.1pg_port = 5432pg_database = kongpg_user = kongpg_password = NONEpg_ssl = offpg_ssl_verify = offcassandra_contact_points = 127.0.0.1cassandra_port = 9042cassandra_keyspace = kongcassandra_timeout = 5000cassandra_ssl = offcassandra_ssl_verify = offcassandra_username = kongcassandra_password = NONEcassandra_consistency = ONEcassandra_lb_policy = RoundRobincassandra_local_datacenter = NONEcassandra_repl_strategy = SimpleStrategycassandra_repl_factor = 1cassandra_data_centers = dc1:2,dc2:3cassandra_schema_consensus_timeout = 10000db_update_frequency = 5db_update_propagation = 0db_cache_ttl = 0db_resurrect_ttl = 30dns_resolver = NONEdns_hostsfile = /etc/hostsdns_order = LAST,SRV,A,CNAMEdns_stale_ttl = 4dns_not_found_ttl = 30dns_error_ttl = 1dns_no_sync = offlua_socket_pool_size = 30lua_ssl_trusted_certificate = NONElua_ssl_verify_depth = 1lua_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: /';  } } 

标签: #nginx大小写不敏感 #nginx 502 494