apisix网关ip-restriction插件使用说明

news/2025/2/8 17:12:37 标签: tcp/ip, 网络, 服务器

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.niftyadmin.cn/n/5845129.html

相关文章

HarmonyOS 5.0应用开发——ContentSlot的使用

【高心星出品】 文章目录 ContentSlot的使用使用方法案例运行结果 完整代码 ContentSlot的使用 用于渲染并管理Native层使用C-API创建的组件同时也支持ArkTS创建的NodeContent对象。 支持混合模式开发,当容器是ArkTS组件,子组件在Native侧创建时&#…

《C#之集训1-20121019c#基础》

 C#是微软公司发布的一种面向对象的、运行于.NET Framework之上的高级程序设计语言。它是微软公司研究员Anders Hejlsberg的最新成果。 C#曾经的它在我眼中是很高大上的,一直没有目睹其风采,现在终于揭开了它神秘的面纱&#xf…

Compose 面试题

https://www.zhihu.com/question/515156409/answer/3122446594 https://juejin.cn/post/7103336251645755429?searchId202502072304248333ED40A0C81FF1ABDD Compose 面试题 Jetpack Compose有了解吗?和传统Android UI有什么不同?DisposableEffect、Si…

青龙面板部署定时脚本自动化运行

1. 青龙面板 1.1. 创建并启动容器 docker run -dit \-v $PWD/ql/data:/ql/data \-p 5700:5700 \-e QlBaseUrl"/" \-e QlPort"5700" \--name qinglong \--hostname qinglong \--restart unless-stopped \whyour/qinglong:2.17.111.2. 查看容器是否启动成功…

golang 开启HTTP代理认证

内部网路不能直接访问外网接口,可以通过代理发送HTTP请求。 HTTP代理服务需要进行认证。 package cmdimport ("fmt""io/ioutil""log""net/http""net/url""strings" )// 推送CBC07功能 func main() {l…

DeepSeek Window本地私有化部署

前言 最近大火的国产AI大模型Deepseek大家应该都不陌生。除了在手机上安装APP或通过官网在线体验,其实我们完全可以在Windows电脑上进行本地部署,从而带来更加便捷的使用体验。 之前也提到过,本地部署AI模型有很多好处,比如&…

【排序算法】桶排序

不能排序负数,适合数据较小但数据量较大的时候使用。 定义了0-9十个桶,先排序个位,向高位排序首先,拿到数值后,先看个位,个位是几就放到对应的桶,以队列的形式进行排列。从0-9取出数据&#xff…

1、k8s基本概念

k8s概述 用于自动部署,自动扩展和管理“容器化应用程序”的开源系统。k8s是google基于go语言开发的自动化运维管理容器。 k8s的全称:kubernetes k8s的版本:1.20------------用的最多的版本,1.18-1.21(1.24---------…