当前位置 : 主页 > 编程语言 > 其它开发 >

【网关开发】ngx嵌套lua时处理CIDR表示的IP地址段

来源:互联网 收集:自由互联 发布时间:2022-06-29
背景 前置网关采用的是ngx中调用lua代码块的形式实现的功能扩展。 在网关开发过程中有很多的waf功能,比较常见就包括黑白名单的功能。为了批量的对某个IP段进行屏蔽,在配置时可能
背景

前置网关采用的是ngx中调用lua代码块的形式实现的功能扩展。
在网关开发过程中有很多的waf功能,比较常见就包括黑白名单的功能。为了批量的对某个IP段进行屏蔽,在配置时可能会以CIDR的形式配置IP段
结合lua代码进行处理

计算思路

我们查看某个IP是否在某个用CIDR表示的IP段时,只需要算出IP段的网络地址(主机位全部置0)作为最小值,计算IP段的广播地址(主机位全部置1)作为最大值即可即可判断当前IP是否在段中

运算过程

这里要用到位运算,由于 Lua 脚本语言本身不支持对数字的二进制操作,MUSHclient 为此提供了一套专门用于二进制操作的函数

bit.band 按位“与”运算
bit.bor 按位“或”运算
bit.lshift(a,b) a向左偏移到b位 相当于<<
bit.rshift(a,b) a逻辑右偏移到b位 相当于>>

local function unsign(n)
    if n < 0 then
        n = 4294967296 + n
    end
    return n
end

local function matchIp(source_ip_value, mask, target_ip_value) 
    local band = bit.band
    local bor = bit.bor
    local lshift = bit.lshift
    local rshift = bit.rshift
    local mask_val = band(lshift(0xFFFFFFFF ,32 - mask) , 0xFFFFFFFF)     --这里将前mask置位1 后32-mask置为0 --> 111...1110000
    local rmask_val = rshift(0xFFFFFFFF ,mask)                                        --这里将前mask置位0 后32-mask置为1  --> 000...0001111
    local min = unsign(band(source_ip_value,mask_val))                             --将source_ip_value的32-mask置为0
    local max = unsign(bor(source_ip_value,rmask_val))                              --将source_ip_value的32-mask置为1
    if mask == 32 then  --特殊处理极端情况
        min = source_ip_value
        max = source_ip_value
    end
    if  target_ip_value <= max and  target_ip_value >= min then
        return true
    end
end

这里可能有疑问source_ip_value哪来的,这里就涉及到如何将IP字符串转换成数值
lua代码 这里使用了C函数,一般会放在其他文件中
比如util/iptoint.lua文件

local ffi = require "ffi"
local C = ffi.C

ffi.cdef[[
	uint32_t ntohl(int netint);
	int inet_addr(const char *ip);
]]

local function iptoint(ip)
	result = C.ntohl(C.inet_addr(ip))
	return result
end

return iptoint

使用:iptoint(ngx.var.remote_addr)
这里用到了两个C函数:
ntohl()将一个无符号长整形数从网络字节顺序转换为主机字节顺序
inet_addr()一个ip地址字符串转换成一个整数值,一般是'a.b.c.d'分成四段

作为对比这里贴出Go的生成代码。
iptoint的go实现,而且相当简单,net包已经实现了大部分功能。

func ip2uint(ipstr string) uint32 {
	ip := net.ParseIP(ipstr)
	if ip == nil {
		return 0
	}
	ip = ip.To4()
	return binary.BigEndian.Uint32(ip)
}

这样就可以在ngx的lua中实现黑白名单段的功能了

上一篇:Python-基础知识汇集
下一篇:没有了
网友评论