apisix网关ip-restriction插件使用说明
ip-restriction插件可以在网关层进行客户端请求ip拦截。
当然了,一般不推荐使用该方法,专业的事专业工具做。建议有条件,还是上防火墙或者waf来做。
官方文档:ip-restriction | Apache APISIX® -- Cloud-Native API Gateway
whitelist:白名单,配置允许访问的ip。
blacklist:黑名单,配置禁止访问的ip。
估计有朋友要问了,我上面那个external_auth的配置节干什么用的。
这个由于业务需要,我们做了一个动态校验请求。就是拦截后会请求这个链接,软如参数,然后如果返回200,就自动放通,如果返回其他状态,就拦截。
这个是自己写脚本实现的。代码如下,其实就是改了ip-restriction的脚本,增加了一个参数。
---
apiVersion: v1
data:
init.lua: |
--
-- Licensed to the Apache Software Foundation (ASF) under one or more
-- contributor license agreements. See the NOTICE file distributed with
-- this work for additional information regarding copyright ownership.
-- The ASF licenses this file to You under the Apache License, Version 2.0
-- (the "License"); you may not use this file except in compliance with
-- the License. You may obtain a copy of the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
--
local ipairs = ipairs
local core = require("apisix.core")
local http = require("resty.http")
local lrucache = core.lrucache.new({
ttl = 300, count = 512
})
local schema = {
type = "object",
properties = {
message = {
type = "string",
minLength = 1,
maxLength = 1024,
default = "Your IP address is not allowed"
},
whitelist = {
type = "array",
items = {anyOf = core.schema.ip_def},
minItems = 1
},
blacklist = {
type = "array",
items = {anyOf = core.schema.ip_def},
minItems = 1
},
external_auth = {
type = "object",
properties = {
uri = {type = "string"},
timeout = {
type = "integer",
minimum = 1,
maximum = 60000,
default = 3000,
description = "timeout in milliseconds",
},
method = {
type = "string",
default = "GET",
enum = {"GET", "POST"},
description = "the method for client to request the auth service"
},
headers = {type = "object"},
ip_param_key = {type = "string", default = "ip"},
allow_degradation = {type = "boolean", default = true},
rejected_code = {
type = "integer", minimum = 200, maximum = 599, default = 403
},
rejected_msg = {
type = "string", minLength = 1
}
}
}
},
anyOf = {
{required = {"whitelist"}},
{required = {"blacklist"}},
{required = {"external_auth"}},
}
}
local plugin_name = "ip-restriction"
local _M = {
version = 0.1,
priority = 3000,
name = plugin_name,
schema = schema,
}
function _M.check_schema(conf)
local ok, err = core.schema.check(schema, conf)
if not ok then
return false, err
end
-- we still need this as it is too complex to filter out all invalid IPv6 via regex
if conf.whitelist then
for _, cidr in ipairs(conf.whitelist) do
if not core.ip.validate_cidr_or_ip(cidr) then
return false, "invalid ip address: " .. cidr
end
end
end
if conf.blacklist then
for _, cidr in ipairs(conf.blacklist) do
if not core.ip.validate_cidr_or_ip(cidr) then
return false, "invalid ip address: " .. cidr
end
end
end
return true
end
function _M.restrict(conf, ctx)
local remote_addr = ctx.var.remote_addr
local block = false
if conf.blacklist then
local matcher = lrucache(conf.blacklist, nil,
core.ip.create_ip_matcher, conf.blacklist)
if matcher then
block = matcher:match(remote_addr)
end
end
if block then
-- 黑名单中的 ip 直接拒绝
return 403, { message = conf.message }
end
local in_white = false
if conf.whitelist then
local matcher = lrucache(conf.whitelist, nil,
core.ip.create_ip_matcher, conf.whitelist)
if matcher then
in_white = matcher:match(remote_addr)
end
end
if in_white then
-- 白名单中的 ip 直接放行
return
end
if conf.external_auth then
local external_auth = conf.external_auth
local params = {
method = external_auth.request_method
}
local httpc = http.new()
httpc:set_timeout(external_auth.timeout)
local uri = external_auth.ip_param_key .. '=' .. remote_addr
if string.find(external_auth.uri, "?") then
uri = external_auth.uri .. "&" .. uri
else
uri = external_auth.uri .. "?" .. uri
end
local res, err = httpc:request_uri(uri, params)
-- 校验 ip 的服务不可用的时候
if not res then
core.log.error("failed to auth ip, err: ", err)
if conf.external_auth.allow_degradation then
-- 允许放行
return
else
return external_auth.rejected_code, { message = conf.message }
end
end
-- 返回值为 2xx 的时候表示校验通过
if res.status >= 300 then
return external_auth.rejected_code, { message = conf.message }
end
end
end
return _M
kind: ConfigMap
metadata:
name: ip-restriction
namespace: apisix-szxc-qxz2v397g6
resourceVersion: '224926381'
核心部分:
然后请求的接口,就可以自己编写了,相对更灵活。
对了,上面贴的是k8s的yaml,这是一个comfigmap,注入到apisix容器中,替换了原文件。
其实apisix的组件都是lua脚本实现的,很灵活,都可以根据需要自行重写。