1. ipset 的作用
ipset 是 Linux 内核的一个数据结构,可由 ipset 程序管理。取决在于类型上, ipset 可以存储 IP 地址, 网络, (TCP/UDP) 端口号, MAC地址, 接口名称或它们的组合,以确保将条目与集合匹配时的闪电速度。
- 存储多个 IP 地址或端口号并匹配 iptables 一举收集;
- 针对 IP 地址或端口动态更新 iptables 规则,而不会降低性能;
- 通过一个 iptables 规则和优势表达基于 IP 地址和端口的复杂规则集 从 IP 集的速度。
2. ipset 使用方法
// 创建
ipset create myset hash:ip
ipset create myset hash:net
// 销毁
ipset destroy myset
// 添加条目
ipset add myset 192.168.1.1
// 删除,清空条目
ipset del myset 192.168.1.1
ipset flush myset
ipset flush
// 查询条目
ipset list
ipset list myset
// 测试条目
ipset test myset 192.168.1.1
// ipset 和 iptables
iptables -I INPUT -m set --match-set myset src -m set --match-set myset1 dst -p tcp -j DROP
// 规则保存到文件
ipset save myset -f myset.txt
// 导入规则
ipset restore -f myset.txt
// 超时时间
ipset create myset hash:net timeout 600
默认值 0,表示永久。
// family 支持 默认inet
ipset create myset hash:ip family inet
ipset create myset hash:ip family inet6
3. ipset datatype
名称 | 说明 | 示例 |
bitmap:ip | 使用内存范围存储 IPv4 格式的主机或网络地址。可存储 65536 个条目。 | ipset create foo bitmap:ip range 192.168.0.0/16 |
bitmap:ip,mac | 使用内存范围存储 IPv4 + MAC 地址。可存储 65536 个条目。 | ipset create foo bitmap:ip,mac range 192.168.0.0/16 |
bitmap:port | 使用内存范围存储端口号。可存储 65536 个端口条目。 | ipset create foo bitmap:port range 0-1024 |
hash:ip | 使用散列存储 IP 或网络地址。 | ipset create foo hash:ip netmask 30 |
hash:mac | 使用散列存储 MAC 地址。 | ipset create foo hash:mac |
hash:ip,mac | 使用散列存储 IP + MAC 地址。 | ipset create foo hash:ip,mac |
hash:net | 使用散列存储网络地址。 | ipset create foo hash:net |
hash:net,net | 使用散列存储网络地址 + 网络地址。 | ipset create foo hash:net,net |
hash:ip,port | 使用散列存储 IP + 端口。 | ipset create foo hash:ip,port |
hash:net,port | 使用散列存储网络地址 + 端口。 | ipset create foo hash:net,port |
hash:ip,port,ip | 使用散列存储 IP + 端口 + IP。 | ipset create foo hash:ip,port,ip |
hash:ip,port,net | 使用散列存储 IP + 端口 + 网络地址。 | ipset create foo hash:ip,port,net |
hash:ip,mark | 使用散列存储 IP + 包标记。 | ipset create foo hash:ip,mark |
hash:net,port,net | 使用哈希存储网络地址 + 端口 + 网络地址。 | ipset create foo hash:net,port,net |
hash:net,iface | 使用散列存储网络地址 + 网卡名称。 | ipset create foo hash:net,iface |
list:set | 使用列表存储集合名称。 |
4. ipset API
#include <libipset/ipset.h>
//在库中加载支持的 ipset 类型并使它们 可用于 IPSET 接口。
void ipset_load_types(void)
//初始化 ipset 接口:分配并初始化所需的内部结构,打开 NetLink 通道。
//函数返回 类型为 struct ipset * 或 NULL 的库接口结构,失败时为 NULL。
struct ipset * ipset_init(void)
//使用已经初始化的ipset库结构解析字符串argv数组的argc长度。
//如果命令解析成功,则将其提交给内核执行。在错误的情况下,打印文本错误消息并返回负数。
int ipset_parse_argv(struct ipset *ipset, int argc, char *argv[])
//该行应该包含还原格式的单个ipset命令。如果命令解析成功,则将其提交给内核执行。
//在错误的情况下,打印文本错误消息并返回负数。
int ipset_parse_line(struct ipset *ipset, char *line)
//流可能包含还原格式的多个换行符分隔的ipset命令。
//对命令进行解析,然后分批提交给内核,以提高效率。在错误的情况下,打印文本错误消息并返回负数。
int ipset_parse_stream(struct ipset *ipset, FILE *f)
//关闭 netlink 通道,关闭打开的流并释放分配的流 由 IPSET 库结构保存的结构。
int ipset_fini(struct ipset *ipset)
//这个函数用于设置自定义的错误处理和输出方式。
int ipset_custom_printf(struct ipset *ipset, ipset_custom_errorfn custom_error,
ipset_standard_errorfn standard_error, ipset_print_outfn outfn, void *p)
//这个函数用于创建一个 IP 集合会话,返回一个指向会话对象的指针。
struct ipset_session * ipset_session(struct ipset *ipset)
//这个函数用于进行完全的输入输出操作,可以将 IP 集合会话保存到文件中或从文件中加载。
int ipset_session_full_io(struct ipset_session *session, const char *filename, enum ipset_io_type what)
//这个函数用于进行普通的输入输出操作,可以将 IP 集合会话保存到文件中或从文件中加载。
int ipset_session_normal_io(struct ipset_session *session, const char *filename, enum ipset_io_type what)
//这个函数用于获取 IP 集合会话的文件流,可以用于进一步的文件操作。
FILE * ipset_session_io_stream(struct ipset_session *session, enum ipset_io_type what)
//这个函数用于关闭 IP 集合会话的文件流。
int ipset_session_io_close(struct ipset_session *session, enum ipset_io_type what)
5. ipset 代码示例
#include <stdio.h>
#include <stdlib.h>
#include <libipset/ipset.h>
int main() {
// 初始化 ipset 对象
struct ipset *ipset = ipset_init();
if (ipset == NULL) {
fprintf(stderr, "Failed to initialize ipset\n");
return 1;
}
// 创建一个 IP 集合会话
struct ipset_session *session = ipset_session(ipset);
if (session == NULL) {
fprintf(stderr, "Failed to create ipset session\n");
ipset_fini(ipset);
return 1;
}
// 添加一些 IP 地址到集合中
ipset_parse_line(ipset, "create myset hash:ip");
ipset_parse_line(ipset, "add myset 192.168.1.1");
ipset_parse_line(ipset, "add myset 192.168.1.2");
// 保存集合到文件
ipset_session_full_io(session, "ipset_file.txt", IPSET_SAVE);
// 清空集合
ipset_parse_line(ipset, "flush myset");
// 从文件中加载集合
ipset_session_full_io(session, "ipset_file.txt", IPSET_RESTORE);
// 打印集合内容
ipset_custom_printf(ipset, NULL, NULL, ipset_print_plain, stdout);
// 释放资源
ipset_session_io_close(session, IPSET_SAVE);
ipset_session_io_close(session, IPSET_RESTORE);
ipset_session(session);
ipset_fini(ipset);
return 0;
}
//上述代码编译需要链接动态库
gcc -o my_program my_program.c -lipset