Android网络安全:Netfilter与iptables

Android 4.4.4

1、Netfilter与iptables关系

Netfilter:

    http://www.netfilter.org/:
    Netfilter is a framework provided by the Linux kernel that allows various networking-related operations to be
    implemented in the form of customized handlers. 

    Netfilter offers various functions and operations for packet filtering, network address translation, and port translation, which provide the functionality required for directing packets through a network, as well as for providing ability to prohibit packets from reaching sensitive locations within a computer network.

Netfilter 利用一些封包过滤的【规则】设定,来定义出什么数据包可以接收, 什么数据包需要剔除。位于内核层。

iptables 通过命令的方式对Netfilter 规则进行排序与修改。位于用户层。

用户层的iptables和内核层的Netfilter之间的关系和其通讯方式:

注:感谢,图片来自http://blog.chinaunix.net/uid-23069658-id-3160506.html

Netfilter 与IP 协议栈无缝契合,因此它的效率非常的高。主要完成:

拒绝让 Internet 的封包进入主机的某些端口口
拒绝让某些来源 IP 的封包进入
拒绝让带有某些特殊标志 (flag) 的封包进入,最常拒绝的就是带有 SYN 的主动联机的flag,只要一经发现就将该封包丢弃
分析硬件地址 (MAC) 来决定联机与否

2、Netfilter工作流程

注:感谢,图片来自http://blog.chinaunix.net/uid-23069658-id-3160506.html

收到的每个数据包,都从“A”点进来,经过路由判决,如果是发送给本机的就经过“B”点,然后往协议栈的上层继续传递;否则,如果该数据包的目的地是不本机,那么就经过“C”点,然后顺着“E”点将该包转发出去。

Netfilter在A,B,C,D和E设置回调函数(hook函数),对每一个进出的数据包进行检测,检测完向Netfilter报告一下该数据包的情况,返回结果含:

netfilter.h (kernel\include\uapi\linux)

NF_ACCEPT 继续正常传输数据报,这个返回值告诉 Netfilter:到目前为止,该数据包还是被接受的并且该数据包应当被递交到网络协议栈的下一个阶段。
NF_DROP 丢弃该数据报,不再传输。
NF_STOLEN 回调函数接管该数据报,该回调函数从此开始对数据包的处理,并且Netfilter应当放弃对该数据包做任何的处理。
NF_QUEUE 对该数据报进行排队(通常用于将数据报给用户空间的进程进行处理)
NF_REPEAT 再次调用该回调函数,应当谨慎使用这个值,以免造成死循环。
NF_STOP 功能和NF_ACCEPT类似但强于NF_ACCEPT,一旦挂接链表中某个hook节点返回NF_STOP,该skb包就立即结束检查而被其他模块接受,不再需要进入后续hook点检查。

和A,B,C,D,E五个点对应的在Netfilter中的术语为:

注:感谢,图片来自http://blog.chinaunix.net/uid-23069658-id-3160506.html

Netfilter支持的协议栈:

netfilter.h (kernel\include\uapi\linux)

enum {
	NFPROTO_IPV4   =  2,
	NFPROTO_ARP    =  3,
	NFPROTO_BRIDGE =  7,
	NFPROTO_IPV6   = 10,
	NFPROTO_DECNET = 12,
};

以Ipv4为例,从协议栈正常流程,经过A,B,C,D,E每个点时,切入到Netfilter框架中,依次去调用每个HOOK点的回调(钩子)函数,检查完后返回,根据结果确定之后走向:

ip_input.c (kernel\net\ipv4)

ip_output.c (kernel\net\ipv4)

ip_forward.c (kernel\net\ipv4)

(1):NF_HOOK(NFPROTO_IPV4, NF_INET_PRE_ROUTING, skb, dev, NULL,ip_rcv_finish)
(2):NF_HOOK(NFPROTO_IPV4, NF_INET_LOCAL_IN, skb, skb->dev, NULL,ip_local_deliver_finish);
(3):NF_HOOK(NFPROTO_IPV4, NF_INET_FORWARD, skb, skb->dev, rt->u.dst.dev,ip_forward_finish);
(4):NF_HOOK(NFPROTO_IPV4, NF_INET_LOCAL_OUT, skb, NULL, skb->dst->dev, dst_output);
(5):NF_HOOK_COND(NFPROTO_IPV4, NF_INET_POST_ROUTING, skb, NULL, dev,ip_finish_output, cond);

NF_HOOK(pf, hook, skb, in,  out, okfn)
pf:协议栈名称,定义在socket.h (kernel\include\linux)
hook:HOOK点的名字,对于IPv4就是上述五个值
skb:内核中网络数据包的结构体
in:数据包进来的设备,以struct net_device结构表示
out:数据包出去的设备,以struct net_device结构表示
okfn:函数指针,该HOOK点的所有登记的函数调用完后调用该函数

3、用户层iptables与内核交互方式、流程

Netfilter框架具有三个主要模块,如下:

iptables维护这三张表,查看或设置使用参数-t:

iptables -t filter -L
iptables -t nat -L
iptables -t mangle -L

内核负责和用户层iptables命令交互的是ip-tables模块:

ip_tables.c (kernel\net\ipv4\netfilter)	56679	2016-03-08
static int __init ip_tables_init(void)
{
	/* Register setsockopt */
	ret = nf_register_sockopt(&ipt_sockopts);
	if (ret < 0)
		goto err5;
	pr_info("(C) 2000-2006 Netfilter Core Team\n"); // 系统启动打印该log
	return 0;
}
static void __exit ip_tables_fini(void)

module_init(ip_tables_init);
module_exit(ip_tables_fini);

用户层iptables通过setsockopt/getsockopt设置/查询这三张表,并最终调用ip_tables_init()注册的do_ipt_set_ctl/do_ipt_get_ctl()函数:

ip_tables.c (kernel\net\ipv4\netfilter)
static struct nf_sockopt_ops ipt_sockopts = {
	.set		= do_ipt_set_ctl,
	.get		= do_ipt_get_ctl,
	.owner		= THIS_MODULE,
};
ip_tables.c (kernel\net\ipv4\netfilter)
static int do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
{
	switch (cmd) {
	case IPT_SO_SET_REPLACE:
		ret = do_replace(sock_net(sk), user, len);
		break;
	case IPT_SO_SET_ADD_COUNTERS:
		ret = do_add_counters(sock_net(sk), user, len, 0);
		break;
	default:
		ret = -EINVAL;
	}
	return ret;
}
static intdo_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
{
	switch (cmd) {
	case IPT_SO_GET_INFO:
		ret = get_info(sock_net(sk), user, len, 0);
		break;
	case IPT_SO_GET_ENTRIES:
		ret = get_entries(sock_net(sk), user, len);
		break;
	case IPT_SO_GET_REVISION_MATCH:
	case IPT_SO_GET_REVISION_TARGET:
		break;
	}
	default:
		ret = -EINVAL;
	}
	return ret;
}

4、Netfilter默认rules的创建

在没有使用iptables命令设置规则表(filter表、nat表、mangle表)的情况下,系统也自动生成默认的规则表,如下filter表:

(只列出INPUT链)

[email protected]:/ # iptables -t filter -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
bw_INPUT   all  --  anywhere             anywhere
fw_INPUT   all  --  anywhere             anywhere

这个默认规则在代码里通过iptables命令生成:

CommandListener.cpp (system\netd)
CommandListener::CommandListener(UidMarkMap *map) :FrameworkListener("netd", true)
{
    // Create chains for children modules
    createChildChains(V4V6, "filter", "INPUT", FILTER_INPUT);
    createChildChains(V4V6, "filter", "FORWARD", FILTER_FORWARD);
    createChildChains(V4V6, "filter", "OUTPUT", FILTER_OUTPUT);
    createChildChains(V4V6, "raw", "PREROUTING", RAW_PREROUTING);
    createChildChains(V4V6, "mangle", "POSTROUTING", MANGLE_POSTROUTING);
    createChildChains(V4V6, "mangle", "OUTPUT", MANGLE_OUTPUT);
    createChildChains(V4, "nat", "PREROUTING", NAT_PREROUTING);
    createChildChains(V4, "nat", "POSTROUTING", NAT_POSTROUTING);
}
    CommandListener.cpp (system\netd)
    /**
     * List of module chains to be created, along with explicit ordering. ORDERING
     * IS CRITICAL, AND SHOULD BE TRIPLE-CHECKED WITH EACH CHANGE.
     */
    static const char* FILTER_INPUT[] = {
            // Bandwidth should always be early in input chain, to make sure we
            // correctly count incoming traffic against data plan.
            BandwidthController::LOCAL_INPUT, // "bw_INPUT"
            FirewallController::LOCAL_INPUT, // "fw_INPUT"
            NULL,
    };

    【log截图中绿色框部分】
    void createChildChains(IptablesTarget target, const char* table, const char* parentChain, const char** childChains);
    -->int execIptablesSilently(IptablesTarget target, ...);
    ---->int execIptables(IptablesTarget target, bool silent, va_list args) {
            const char *argv[argsList.size()];
            ...
            argv[0] = IPTABLES_PATH; // IPTABLES_PATH = "/system/bin/iptables"
        }
    ------>int execIptablesCommand(int argc, const char *argv[], bool silent);
    -------->int android_fork_execvp(int argc, char* argv[], int *status,boolignore_int_quit, bool logwrap) {
                 pid = fork();
                 if (pid == 0) {
                     child(argc, argv);
                 }
             }
    ---------->static void child(int argc, char* argv[]) {
                   // create null terminated argv_child array
                   char* argv_child[argc + 1];
                   memcpy(argv_child, argv, argc * sizeof(char *));
                   argv_child[argc] = NULL;
                   if (execvp(argv_child[0], argv_child)) {
                        FATAL_CHILD("executing %s failed: %s\n", argv_child[0],
                        strerror(errno));
                   }
               }

还有一个地方,也用iptables命令设置了规则表:

int NatController::setupIptablesHooks() {
    res = setDefaults();
【log截图中蓝色框部分】
struct CommandsAndArgs defaultCommands[] = {
        {{IPTABLES_PATH, "-F", LOCAL_TETHER_COUNTERS_CHAIN,}, 0},
        {{IPTABLES_PATH, "-X", LOCAL_TETHER_COUNTERS_CHAIN,}, 0},
        {{IPTABLES_PATH, "-N", LOCAL_TETHER_COUNTERS_CHAIN,}, 1},
    };
    for (unsigned int cmdNum = 0; cmdNum < ARRAY_SIZE; cmdNum++) {
        if (runCmd(ARRAY_SIZE, defaultCommands[cmdNum].cmd) && defaultCommands[cmdNum].checkRes) {}
    }
}
【log截图中黄色框部分】
int NatController::setDefaults() {
    struct CommandsAndArgs defaultCommands[] = {
        {{IPTABLES_PATH, "-F", LOCAL_FORWARD,}, 1},
        {{IPTABLES_PATH, "-A", LOCAL_FORWARD, "-j", "DROP"}, 1},
        {{IPTABLES_PATH, "-t", "nat", "-F", LOCAL_NAT_POSTROUTING}, 1},
        {{IP_PATH, "rule", "flush"}, 0},
        {{IP_PATH, "-6", "rule", "flush"}, 0},
        {{IP_PATH, "rule", "add", "from", "all", "lookup", "default", "prio", "32767"}, 0},
        {{IP_PATH, "rule", "add", "from", "all", "lookup", "main", "prio", "32766"}, 0},
        {{IP_PATH, "-6", "rule", "add", "from", "all", "lookup", "default", "prio", "32767"}, 0},
        {{IP_PATH, "-6", "rule", "add", "from", "all", "lookup", "main", "prio", "32766"}, 0},
        {{IP_PATH, "route", "flush", "cache"}, 0},
    };
    for (unsigned int cmdNum = 0; cmdNum < ARRAY_SIZE; cmdNum++) {
        if (runCmd(ARRAY_SIZE, defaultCommands[cmdNum].cmd) && defaultCommands[cmdNum].checkRes) {}
    }
}
int NatController::runCmd(int argc, const char **argv) {
    res = android_fork_execvp(argc, (char **)argv, NULL, false, false);
    ALOGV("runCmd(%s) res=%d", full_cmd.c_str(), res);
    return res;
}

Log:

参考资料:

1、鸟哥的Linux私房菜服务器架设篇(第三版)——第九章、防火墙与 NAT 服务器
2、http://www.netfilter.org/
3、iptables使用文档:https://www.frozentux.net/iptables-tutorial/iptables-tutorial.html
4、系列:
   (一)洞悉linux下的Netfilter&iptables:什么是Netfilter?()
   (二)洞悉linux下的Netfilter&iptables:内核中的ip_tables小觑 (http://blog.chinaunix.net/uid-23069658-id-3162264.html)
   (三)洞悉linux下的Netfilter&iptables:内核中的rule,match和target (http://blog.chinaunix.net/uid-23069658-id-3163999.html)
   (四)洞悉linux下的Netfilter&iptables:包过滤子系统iptable_filter (http://blog.chinaunix.net/uid-23069658-id-3166140.html)

源码路径:

arp_tables.c (kernel\net\ipv4\netfilter)
BandwidthController.cpp (system\netd)
BandwidthController.h (system\netd)
CommandListener.cpp (system\netd)
CommandListener.h (system\netd)
core.c (kernel\net\netfilter)
FirewallController.cpp (system\netd)
FirewallController.h (system\netd)
iptables.h (external\iptables\include)
iptable_filter.c (kernel\net\ipv4\netfilter)
iptable_nat.c (kernel\net\ipv4\netfilter)
iptable_raw.c (kernel\net\ipv4\netfilter)
ip_forward.c (kernel\net\ipv4)
ip_input.c (kernel\net\ipv4)
ip_output.c (kernel\net\ipv4)
ip_tables.c (kernel\net\ipv4\netfilter)
ip_tables.h (kernel\include\linux\netfilter_ipv4)
ip_tables.h (kernel\include\uapi\linux\netfilter_ipv4)
kmod.h (kernel\include\linux)
logwrap.c (system\core\logwrapper)
logwrap.h (system\core\logwrapper\include\logwrap)
NetdCommand.cpp (system\netd)
NetdCommand.h (system\netd)
NetdConstants.cpp (system\netd)
NetdConstants.h (system\netd)
netfilter.h (kernel\include\linux)
netfilter.h (kernel\include\uapi\linux)
nfnetlink.c (kernel\net\netfilter)
nf_sockopt.c (kernel\net\netfilter)
socket.h (kernel\include\linux)
x_tables.c (kernel\net\netfilter)
x_tables.h (kernel\include\linux\netfilter)
x_tables.h (kernel\include\uapi\linux\netfilter)
时间: 2024-10-13 02:11:17

Android网络安全:Netfilter与iptables的相关文章

浅析NetFilter和iptables

摘自:https://blog.csdn.net/wxywxywxy110/article/details/78621789 一:介绍NetFilter和iptables框架 如上图,分三种情况介绍数据包和钩子函数的关系: 当数据包从物理层和数据链路层传输过来,如果数据包是访问Linux主机本身.则经过PRE_ROUTING和LOCAL_IN钩子函数,到达传输层和应用层. 当数据包从物理层和数据链路层传输过来,如果数据包需要转发,则经过PRE_ROUTING.FORWARD和POST_ROUTI

Netfilter/Ebtables/Iptables本地和转发流量的路径

Netfilter框架: 测试环境: 准备netfilter 环境:测试STA->AP的流量 firewall-rules stop iptables -t mangle -A PREROUTING -s 192.168.1.131 -p icmp -j LOG --log-prefix="IPT_MANGLE_PRER_131_ICMP: " iptables -t nat -A PREROUTING -s 192.168.1.131 -p icmp -j LOG --log-

防火墙及netfilter基础iptables基本用法

iptables firewall: 主机防火墙 网络防火墙 工作于主机或网络的边缘,对于进出的报文根据事先定义的规则作检查,将那些能够被规则所匹配到的报文作出相应处理的组件. 网络防火墙: 专业的硬件防火墙: checkpoint,netscreen 主机: iptables: 程序 iptables:规则编写工具 netfilter: 网络过滤器, 内核中工作在TCP/IP网络协议栈上的框架: IDS:IntrusionDetecting System NIDS HIDS IPS:Intru

2018.5.8 七周三次课(firewalld和netfilter,iptables语法)

Linux网络相关 centOS版本6里,如果想用ifconfig 得安装个net-tools [[email protected] ~]# yum install -y net-tools 关闭一个网卡 [[email protected] ~]# ifdown ens33 开启网卡 [[email protected] ~]# ifup ens33 重启网卡 [[email protected] ~]# ifdown ens33 && ifup ens33 添加一个虚拟网卡 [[ema

Linux网络相关命令firewalld和netfilter、iptables 使用(6/22)

iptables和netfilter的关系: netfilter在内核空间的代码根据table中的rules,完成对packet的分析和处置.但是这些table中的具体的防火墙rules,还是必须由系统管理员亲自编写.内核中的netfilter只是提供了一个机制,它并不知道该怎样利用这个机制,写出合适的rules,来实现一个网络防火墙. 那么,系统管理员编写的rules,怎样进入位于内核空间中的netfilter维护的table中去呢?这个任务是由iptables这个工具来完成的. 说白了就是n

netfilter及iptables基本概念

input入向流量      选择相对应的表    修改数据包的地址   高级参数设置 output出向流量 forward转发流量 prerouting路由前流量 postrouting路由后的流量 用的是prerouting.postrouting

Netfilter 和 iptables

原文地址:https://www.cnblogs.com/superxuezhazha/p/11387218.html

Android中网络流量控制(防火墙)——Iptables

Iptables简介 iptables是与最新的 2.6.x 版本 Linux 内核集成的 IP 信息包过滤系统.如果 Linux 系统连接到因特网或 LAN.服务器或连接 LAN 和因特网的代理服务器, 则该系统有利于在 Linux 系统上更好地控制 IP 信息包过滤和防火墙配置. Iptables工作原理 netfilter/iptablesIP 信息包过滤系统是一种功能强大的工具, 可用于添加.编辑和除去规则,这些规则是在做信息包过滤决定时,防火墙所遵循和组成的规则.这些规则存储在专用的信

Iptables 网络安全

第1章 Iptables网络安全 1.1 Iptables防火墙介绍 Netfilter/Iptables(以下简称Iptables)是unix/linux自带的一款优秀且开放源代码的完全自由的基于包过滤的防火墙工具 Netfilter一个系统的内核模块,通过netfilter内核控制硬件设备 Iptables相当于是一个控制软件 iptables+zebra+squid == 一台硬件防火墙 iptables主要工作在OSI七层的二.三.四层 实现应用层访问控制:nginx WAF实现应用访问