当前位置: 首页 > article >正文

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脚本实现的,很灵活,都可以根据需要自行重写。


http://www.kler.cn/a/536109.html

相关文章:

  • 劳务报酬所得税
  • H266/VVC 环路滤波中去块滤波 DF 技术
  • mongodb 使用内存过大分析
  • 从java角度对比nodejs、fastapi,同步和异步区别
  • 【配置环境】VS Code中JavaScript环境搭建
  • go流程控制
  • Spring Boot实现多数据源连接和切换
  • Linux Windows macOS如何安装Ollama
  • QQ自动发送消息
  • TypeScript 快速上手 ------- 学习笔记分享
  • SMU winter 2025 Personal Round 2
  • RabbitMQ:windows最新版本4.0.5安装方案
  • Rust unresolved import `crate::xxx` 报错解决
  • C++11—可变参数模板
  • 【CS61A 2024秋】Python入门课,全过程记录P6(Week12 Interpreters开始,更新于2025/2/7)
  • 【HarmonyOS NEXT】设备显示白屏 syswarning happended in XXX
  • C++ 类和对象 详细版(上)
  • PT2021K 单触控同步输出 IC
  • Python爬虫-如何正确解决起点中文网的无限debugger
  • CF 278A.Circle Line
  • Python中__init__.py文件的作用
  • GitPuk快速安装配置教程(入门级)
  • c# Lazy<T>单例模式 - 延迟初始化单例实例示例与详解
  • Android GPS功耗优化思考点
  • 【Leetcode 热题 100】136. 只出现一次的数字
  • ControlNet 风格迁移介绍