iptables 分析(1)
原文:http://blog.chinaunix.net/uid-24207747-id-2622900.html
iptables 是用户空间中用于管理包过滤及NAT 等的工具应用程序。它设置防火墙的过滤规则,并将规则添加到内核空间的特定信息包过滤表内的链中,通过netfilter框架的hook 函数完成对数据包的过滤工作。它还可以设置nat 表的规则实现IP 地址及端口转换,设置mangle 表的规则改变IP 头部信息实现对IP 包更高级的控制.
要分析源码先学会iptabes工具如何使用,看一下它命令help手册,对要分析源码有帮助.执行iptable -h 有:
iptables v1.4.1.1
Usage: iptables -[AD] chain rule-specification [options]
iptables -[RI] chain rulenum rule-specification [options] //用iptables - RI 通过规则的顺序指定
iptables -D chain rulenum [options] //删除指定规则
iptables -[LS] [chain [rulenum]] [options] //用iptables -LFZ 链名 [选项]
iptables -[FZ] [chain] [options]
iptables -[NX] chain //用 -NX 指定链
iptables -E old-chain-name new-chain-name //-E 用新的链名取代旧的链名
iptables -P chain target [options] //指定链的默认目标
iptables -h (print this help information) //帮助
//这些选项指定执行明确的动作:若指令行下没有其他规定,该行只能指定一个选项.对于长格式的命令和选项名,所用字母长度只要保证iptables能从其他选项中区分出该指令就行了
Commands:
Either long or short options are allowed.
--append -A chain Append to chain //在所选择的链末添加一条或更多规则
--delete -D chain Delete matching rule from chain //从所选链中删除一条或更多规则
--delete -D chain rulenum //从所选链中删除一条或更多规则。这条命令可以有两种方法:可以把被删除规则指定为链中的序号(第一条序号为1),或者指定为要匹配的规则
Delete rule rulenum (1 = first) from chain
--insert -I chain [rulenum] //根据给出的规则序号向所选链中插入一条或更多规则。所以,如果规则序号为1,规则会被插入链的头部。这也是不指定规则序号时的默认方式。
Insert in chain as rulenum (default 1=first)
--replace -R chain rulenum //从选中的链中取代一条规则,如果源(地址)或者/与 目的(地址)被转换为多地址,该命令会失败。规则序号从1开始
Replace rule rulenum (1 = first) in chain
--list -L [chain [rulenum]] //显示所选链的所有规则。如果没有选择链,所有链将被显示。也可以和z选项一起使用,这时链会被自动列出和归零。精确输出受其它所给参数影响
List the rules in a chain or all chains
--list-rules -S [chain [rulenum]]
Print the rules in a chain or all chains
--flush -F [chain] Delete all rules in chain or all chains //清空所选链。这等于把所有规则一个个的删除
--zero -Z [chain] Zero counters in chain or all chains //把所有链的包及字节的计数器清空。它可以和 -L配合使用,在清空前察看计数器,请参见前文。
--new -N chain Create a new user-defined chain //根据给出的名称建立一个新的用户定义链。这必须保证没有同名的链存在
--delete-chain //删除指定的用户自定义链。这个链必须没有被引用,如果被引用,在删除之前你必须删除或者替换与之有关的规则。如果没有给出参数,这条命令将试着删除每个非内建的链。
-X [chain] Delete a user-defined chain //清除mangle表中,所有规则链中的规则
--policy -P chain target //设置链的目标规则
Change policy on chain to target
--rename-chain
-E old-chain new-chain //根据用户给出的名字对指定链进行重命名,这仅仅是修饰,对整个表的结构没有影响。TARGETS参数给出一个合法的目标。只有非用户自定义链可以使用规则,而且内建链和用户自定义链都不能是规则的目标
Change chain name, (moving any references)
//这些可被iptables识别的选项可以区分不同的种类
Options:
--proto -p [!] proto protocol: by number or name, eg. 'tcp'//规则或者包检查(待检查包)的协议。指定协议可以是tcp、udp、icmp中的一个或者全部,也可以是数值,代表这些协议中的某一个。当然也可以使用在/etc/protocols中定义的协议名。在协议名前加上"!"表示相反的规则。数字0相当于所有all。Protocol all会匹配所有协议,而且这是缺省时的选项。在和check命令结合时,all可以不被使用。
--source -s [!] address[/mask] //指定源地址,可以是主机名、网络名和清楚的IP地址。mask说明可以是网络掩码或清楚的数字,在网络掩码的左边指定网络掩码左边"1"的个数,因此,mask值为24等于255.255.255.0。在指定地址前加上"!"说明指定了相反的地址段。标志 --src 是这个选项的简写。
source specification
--destination -d [!] address[/mask] //指定目标地址,要获取详细说明请参见 -s标志的说明
destination specification
--in-interface -i [!] input name[+]
network interface name ([+] for wildcard)
--jump -j target //目标跳转,指定规则的目标;也就是说,如果包匹配应当做什么。目标可以是用户自定义链(不是这条规则所在的),某个会立即决定包的命运的专用内建目标,或者一个扩展(参见下面的EXTENSIONS)。如果规则的这个选项被忽略,那么匹配的过程不会对包产生影响,不过规则的计数器会增加。
target for rule (may load target extension)
--goto -g chain
jump to chain with no return
--match -m match
extended match (may load extension)
--numeric -n numeric output of addresses and ports
--out-interface -o [!] output name[+] //输出接口[名称],这是包经由该接口送出的可选的出口名称,包通过该口输出(在链FORWARD、OUTPUT和POSTROUTING中送出的包)。当在接口名前使用"!"说明后,指的是相反的名称。如果接口名后面加上"+",则所有以此接口名开头的接口都会被匹配。如果这个选项被忽略,会假设为"+",那么将匹配所有任意接口。
network interface name ([+] for wildcard)
--table -t table table to manipulate (default: 'filter') //指定表名
--verbose -v verbose mode
--line-numbers print line numbers when listing
--exact -x expand numbers (display exact values)
[!] --fragment -f match second or further fragments only //这意味着在分片的包中,规则只询问第二及以后的片。自那以后由于无法判断这种把包的源端口或目标端口(或者是ICMP类型的),这类包将不能匹配任何指定对他们进行匹配的规则。如果"!"说明用在了"-f"标志之前,表示相反的意思。
--modprobe=<command> try to insert modules using this command
--set-counters PKTS BYTES set the counter during insert/append
[!] --version -V print package version.
进入main函数之前,先看分析几个重要的数据结构,这对看理解源码很有帮助:
iptables 工具还把规则表存储在结构iptc_handle 的变量中,然后,再与内核交互得到或设置规
则表信息。结构iptc_handle 指向一个具体的规则表,表信息从内核中的filter、nat 等表提取.
结构如下:
typedef struct iptc_handle *iptc_handle_t;
#define STRUCT_TC_HANDLE struct iptc_handle
STRUCT_TC_HANDLE
{
int changed; //是否有变化
struct list_head chains; //规则链
struct chain_head *chain_iterator_cur; //当前规则链
struct rule_head *rule_iterator_cur; //当前规则
unsigned int num_chains; //用户定义的链数
struct chain_head **chain_index; /* array for fast chain list access*/
unsigned int chain_index_sz; /* size of chain index array */
STRUCT_GETINFO info; //对应内核结构ipt_getinfo,包含hook 相关信息
STRUCT_GET_ENTRIES *entries; //规则链的规则条目,表对应内核中结构
};
//存储规则
struct rule_head
{
struct list_head list;
struct chain_head *chain;
struct counter_map counter_map;
unsigned int index; /* index (needed for counter_map) */
unsigned int offset; /* offset in rule blob */
enum iptcc_rule_type type;
struct chain_head *jump; /* jump target, if IPTCC_R_JUMP */
unsigned int size; /* size of entry data */
STRUCT_ENTRY entry[0];
};
//存储规则链
struct chain_head
{
struct list_head list;
char name[TABLE_MAXNAMELEN];
unsigned int hooknum; /* hook number+1 if builtin */
unsigned int references; /* how many jumps reference us */
int verdict; /* verdict if builtin */
STRUCT_COUNTERS counters; /* per-chain counters */
struct counter_map counter_map;
unsigned int num_rules; /* number of rules in list */
struct list_head rules; /* list of rules */
unsigned int index; /* index (needed for jump resolval) */
unsigned int head_offset; /* offset in rule blob */
unsigned int foot_index; /* index (needed for counter_map) */
unsigned int foot_offset; /* offset in rule blob */
};
----------------------------------------------------------------------------------------
struct iptables_match *iptables_matches = NULL;
struct iptables_target *iptables_targets = NULL;
1.iptables_match 存储了扩展匹配的操作函数指针,如:扩展匹配模块的初始化、选项分析、检查及帮助等函数,它还包括了结构ipt_entry_match 成员指针,而ipt_entry_match 存储了扩展匹配的条目名及内核使用的匹配操作指针等.ipt_entry_match 将用户空间与内核空间的匹配结构连接起来
2.iptables_target 存储了扩展目标与选项-j 相关的操作函数指针,如:初始化、选项分析、检查及帮助等函数。它在还包括了结构ipt_entry_target 成员,而ipt_entry_target 存储了扩展目标的条目名及内核空间使用的目标操作指针等信息.同上
struct iptables_match
{
struct iptables_match *next;
ipt_chainlabel name; //链名
u_int8_t revision; //匹配模块的版本序号,缺省值为0
const char *version; //版本字符串
size_t size; //匹配的数据大小
size_t userspacesize; //匹配的数据大小,用于在用户空间进行比较
void (*help)(void); //打印使用信息
void (*init)(struct ipt_entry_match *m, unsigned int *nfcache); //初始化匹配
int (*parse)(int c, char **argv, int invert, unsigned int *flags,//分析命令行选项,如果分析完一个选项,返回true
const struct ipt_entry *entry,
unsigned int *nfcache,
struct ipt_entry_match **match);
void (*final_check)(unsigned int flags); //对匹配最终的检查,检查出不正确就退出
void (*print)(const struct ipt_ip *ip, const struct ipt_entry_match *match, intumeric); //打印出匹配信息,放置NULL 在字符串末尾。
void (*save)(const struct ipt_ip *ip, const struct ipt_entry_match *match); //存储分析出的匹配信息到标准输出stdout
const struct option *extra_opts; //指向附加命令行选项链表
unsigned int option_offset;
struct ipt_entry_match *m; //内核中匹配的操作函数及信息
unsigned int mflags;
};
struct ipt_entry_match
{
union {
struct {
u_int16_t match_size; //匹配的大小
char name[IPT_FUNCTION_MAXNAMELEN-1]; //用户空间使用的匹配名
u_int8_t revision; //版本序号
} user; //用户空间匹配条目信息
struct {
u_int16_t match_size; //匹配大小
struct ipt_match *match; //内核空间使用的匹配结构
} kernel; //内核空间使用的匹配结构信息
u_int16_t match_size; //匹配的总大小
} u;
unsigned char data[0];
};
结构 xt_match 定义了扩展匹配的内核模块的操作函数集,其列出如下:
#define ipt_match xt_match
struct xt_match
{
struct list_head list;
const char name[XT_FUNCTION_MAXNAMELEN-1]; //匹配名
u_int8_t revision;
//匹配的实现函数
int (*match)(const struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
const void *matchinfo,
int offset,
unsigned int protoff,
int *hotdrop);
//当用户插入一个条目到这个类型时调用这个函数,返回true 或false
int (*checkentry)(const char *tablename,
const void *ip,
void *matchinfo,
unsigned int matchinfosize,
unsigned int hook_mask);
void (*destroy)(void *matchinfo, unsigned int matchinfosize); //当这个类型的条目被删除时调用
struct modules *me; //如果是内核模块,设置到指针THIS_MODULE,否则为NULL
};
struct option {
const char *name; //长选项的名字
int has_arg; //长选项参数值个数
int *flag; //NULL 时,getopt_long()返回val,否则返回0
int val; //长选项对应的短选项字符
};
----------------------------------------------------------------------------------------
哎,有些结构体必需结构netfiter来看,还找些资料,结构体注解就到这吧,正式进入源码吧,哈哈.
int
main(int argc, char *argv[])
{
int ret;
char *table = "filter"; //默认表filter
iptc_handle_t handle = NULL; //用来储存表的所有规则
program_name = "iptables";
program_version = XTABLES_VERSION;
lib_dir = getenv("XTABLES_LIBDIR"); //得到环境变量
if (lib_dir == NULL) {
lib_dir = getenv("IPTABLES_LIB_DIR");
if (lib_dir != NULL)
fprintf(stderr, "IPTABLES_LIB_DIR is deprecated\n");
}
if (lib_dir == NULL)
lib_dir = XTABLES_LIBDIR;
#ifdef NO_SHARED_LIBS
init_extensions(); //设置版本号
#endif
ret = do_command(argc, argv, &table, &handle); //分析命令选项,将规则存入handle
if (ret)
ret = iptc_commit(&handle); //通过系统调用setsockopt 将规则设置到Linux 的netfilter 模块的规则表中
if (!ret) {
fprintf(stderr, "iptables: %s\n",
iptc_strerror(errno));
if (errno == EAGAIN) {
exit(RESOURCE_PROBLEM);
}
}
exit(!ret);
}
主函数二步工作:1.do_command接受用户输入的命令规则,根据输入的表名,将规则存到结构iptc_handle 2.iptc_commit通过系统调用setsockopt将规则设置到Linux 的netfilter 模块的规则表中.
iptables 分析(1)的更多相关文章
- Openwrt iptables分析
这里将载有Openwrt的WR841N的路由表dump出来分析一下. 这个是dump出iptables的命令 root@OpenWrt:/etc/config# iptables-save 这里分为4 ...
- iptables 分析(三)
原文:http://blog.chinaunix.net/uid-24207747-id-2622902.html find_target查到目标并加载成功,返回一个xtables_target型对象 ...
- iptables 分析(二)
原文:http://blog.chinaunix.net/uid-24207747-id-2622901.html do_command()函数分析 //负责整个用户输入的命令处理 int do_co ...
- 2-12-配置squid代理服务器加快网站访问速度
本节所讲内容: squid服务器常见概念 squid服务器安装及相关配置文件 实战:配置squid正向代理服务器 实战:配置透明squid代理提升访问速度 实战:配置squid反向代理加速度内网web ...
- iptables之LOG目标 被拦截包分析
iptables之LOG目标 问题 在iptables的INPUT链中发现有大量未知包被拦截,这种情况就有两种可能,一是自己的某个服务的iptables端口没有打开,二是服务器正在遭受攻击 分析 这就 ...
- Neutron分析(5)—— neutron-l3-agent中的iptables
一.iptables简介 1.iptables数据包处理流程 以本机为目的的包,由上至下,走左边的路 本机产生的包,从local process开始走左边的路 本机转发的包,由上至下走右边的路 简化流 ...
- 实用防火墙(Iptables)脚本分析
实用防火墙(Iptables)脚本分析 --Redhat,CentOS,Ubuntu等常见Linux发行版中都会预装Iptables防火墙,大多数初学者设置起来由于对这款软件比较陌生,设置起来比较困难 ...
- iptables中ULOG和NFLOG实现分析【转】
原文地址:http://blog.csdn.net/eydwyz/article/details/52456335 ----------原文如下---------------------------- ...
- Linux 为FTP 服务器添加iptables规则--案例分析
一.故障描述 由于开发提出需求,为他们搭建内部ftp服务器,搭建好后,提交给他们,测试可以正常使用.后来过了一段时间后,有一天无法登陆了.于是去ftp主机上检查问题,ftp的配置文件没有改动,端口监听 ...
随机推荐
- 解决matplotlib库在PyCharm和命令行都无法正常显示问题
我们在学习人工智能的时候,会经常用到matplotlib,在学习的时候有一些例子写了代码运行: import matplotlib.pyplot as plt import numpy as np x ...
- C# 托管内存与非托管内存之间的转换
c#有自己的内存回收机制,所以在c#中我们可以只new,不用关心怎样delete,c#使用gc来清理内存,这部分内存就是managed memory,大部分时候我们工作于c#环境中,都是在使用托管内存 ...
- python class和class(object)用法区别
# -*- coding: utf-8 -*- # 经典类或者旧试类 class A: pass a = A() # 新式类 class B(object): pass b = B() # pytho ...
- Hibernate获取数据java.lang.StackOverflowError
原因:因为在重写toString()方法时,把关联的属性也放入到toString方法中了,去掉就可以了. 如:重写的toString方法中不能有关联关系IDCard属性idCard public cl ...
- layui form表单自定义sm格式
1. 新建以下sm样式,保存为layform_sm.css文件名,然后导入到layui.css的后面. .layui-input-sm,.layui-select-sm,.layui-textarea ...
- Win10系统安装UEFI+GPT配置
借鉴博文 https://blog.csdn.net/lyj_viviani/article/details/51800445 安装win10需要改用UEFI引导模式,硬盘需要换成GUID格式; ...
- 1.介绍(introduction)
这里主要记录一本书的学习过程: 条件独立: 意思是X和Y在given Z的情况下是独立的. 满足P(X,Y|Z) = P(X|Z)*P(Y|Z)以及P(X|Y,Z) = P(X|Z) 条件独立的一些性 ...
- asp.net core cors中间件
public class CorsMiddleware { private readonly RequestDelegate _next; public CorsMiddleware(RequestD ...
- http 请求 post get 长度限制
一.问题起因在某项目释放后Bug统计的附件<释放后问题>里有: 问题 原因 分析 备注 CSV处理时,如果处理的主题数过多,发生URL参数上限的错误: 可变长度的参数通过UR ...
- [踩坑日记]spring mvc
目录 找不到javax.servlet.ServletException的类文件 idea 清除tomcat缓存 IOException parsing XML document from Servl ...