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 = ipairslocal 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 thenreturn false, errend-- we still need this as it is too complex to filter out all invalid IPv6 via regexif conf.whitelist thenfor _, cidr in ipairs(conf.whitelist) doif not core.ip.validate_cidr_or_ip(cidr) thenreturn false, "invalid ip address: " .. cidrendendendif conf.blacklist thenfor _, cidr in ipairs(conf.blacklist) doif not core.ip.validate_cidr_or_ip(cidr) thenreturn false, "invalid ip address: " .. cidrendendendreturn trueendfunction _M.restrict(conf, ctx)local remote_addr = ctx.var.remote_addrlocal block = falseif conf.blacklist thenlocal matcher = lrucache(conf.blacklist, nil,core.ip.create_ip_matcher, conf.blacklist)if matcher thenblock = matcher:match(remote_addr)endendif block then-- 黑名单中的 ip 直接拒绝return 403, { message = conf.message }endlocal in_white = falseif conf.whitelist thenlocal matcher = lrucache(conf.whitelist, nil,core.ip.create_ip_matcher, conf.whitelist)if matcher thenin_white = matcher:match(remote_addr)endendif in_white then-- 白名单中的 ip 直接放行returnendif conf.external_auth thenlocal external_auth = conf.external_authlocal params = {method = external_auth.request_method}local httpc = http.new()httpc:set_timeout(external_auth.timeout)local uri = external_auth.ip_param_key .. '=' .. remote_addrif string.find(external_auth.uri, "?") thenuri = external_auth.uri .. "&" .. urielseuri = external_auth.uri .. "?" .. uriendlocal res, err = httpc:request_uri(uri, params)-- 校验 ip 的服务不可用的时候if not res thencore.log.error("failed to auth ip, err: ", err)if conf.external_auth.allow_degradation then-- 允许放行returnelsereturn external_auth.rejected_code, { message = conf.message }endend-- 返回值为 2xx 的时候表示校验通过if res.status >= 300 thenreturn external_auth.rejected_code, { message = conf.message }endendendreturn _M
kind: ConfigMap
metadata:name: ip-restrictionnamespace: apisix-szxc-qxz2v397g6resourceVersion: '224926381'
核心部分:
然后请求的接口,就可以自己编写了,相对更灵活。
对了,上面贴的是k8s的yaml,这是一个comfigmap,注入到apisix容器中,替换了原文件。
其实apisix的组件都是lua脚本实现的,很灵活,都可以根据需要自行重写。