Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android網絡安全:Netfilter與iptables

Android網絡安全:Netfilter與iptables

編輯:關於Android編程

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之間的關系和其通訊方式:

\

 

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鏈)
root@KoolRegister:/ # 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)

 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved