Android Iptables 客制化方法及基本使用
iptables 是一个在Linux内核集成的IP信息包过滤系统,用于控制IP信息包过滤和防火墙配置,通过存储在数据包过滤表中的规则,在不同的链中做出数据包过滤决定。
Android 是基于 Linux 的操作系统,支持 Iptables。执行 Iptables 命令需要 root 权限。
Android netd 的自定义链
以 INPUT 链为例子,Andorid 会自定义 bw_INPUT、fw_INPUT 等链,链到 INPUT 链上
# iptables -L
Chain INPUT (policy ACCEPT)
target prot opt source destination
bw_INPUT all -- anywhere anywhere
fw_INPUT all -- anywhere anywhere
Controllers 执行 init() 方法时会先执行 initChildChains 方法, 在 INPUT 链下创造子链
void Controllers::initChildChains() {
/*
* This is the only time we touch top-level chains in iptables; controllers
* should only mutate rules inside of their children chains, as created by
* the constants above.
*
* Modules should never ACCEPT packets (except in well-justified cases);
* they should instead defer to any remaining modules using RETURN, or
* otherwise DROP/REJECT.
*/
// Create chains for child modules.
createChildChains(V4V6, "filter", "INPUT", FILTER_INPUT, true);
createChildChains(V4V6, "filter", "FORWARD", FILTER_FORWARD, true);
createChildChains(V4V6, "raw", "PREROUTING", RAW_PREROUTING, true);
createChildChains(V4V6, "mangle", "FORWARD", MANGLE_FORWARD, true);
createChildChains(V4V6, "mangle", "INPUT", MANGLE_INPUT, true);
createChildChains(V4, "nat", "PREROUTING", NAT_PREROUTING, true);
createChildChains(V4, "nat", "POSTROUTING", NAT_POSTROUTING, true);
createChildChains(V4, "filter", "OUTPUT", FILTER_OUTPUT, false);
createChildChains(V6, "filter", "OUTPUT", FILTER_OUTPUT, false);
createChildChains(V4, "mangle", "POSTROUTING", MANGLE_POSTROUTING, false);
createChildChains(V6, "mangle", "POSTROUTING", MANGLE_POSTROUTING, false);
}
FILTER_INPUT 是子链的集合,定义顺序,会从上往下添加,先添加的子链具有较高的优先级,以 FILTER_INPUT 为例,FILTER_INPUT 定义为:
/**
* List of module chains to be created, along with explicit ordering. ORDERING
* IS CRITICAL, AND SHOULD BE TRIPLE-CHECKED WITH EACH CHANGE.
*/
static const std::vector<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,
FirewallController::LOCAL_INPUT,
};
createChildChains 方法定义如下
void Controllers::createChildChains(IptablesTarget target, const char* table,
const char* parentChain,
const std::vector<const char*>& childChains,
bool exclusive) {
std::string command = StringPrintf("*%s\n", table);
// We cannot just clear all the chains we create because vendor code modifies filter OUTPUT and
// mangle POSTROUTING directly. So:
//
// - If we're the exclusive owner of this chain, simply clear it entirely.
// - If not, then list the chain's current contents to ensure that if we restart after a crash,
// we leave the existing rules alone in the positions they currently occupy. This is faster
// than blindly deleting our rules and recreating them, because deleting a rule that doesn't
// exists causes iptables-restore to quit, which takes ~30ms per delete. It's also more
// correct, because if we delete rules and re-add them, they'll be in the wrong position with
// regards to the vendor rules.
//
// TODO: Make all chains exclusive once vendor code uses the oem_* rules.
std::set<std::string> existingChildChains;
if (exclusive) {
// Just running ":chain -" flushes user-defined chains, but not built-in chains like INPUT.
// Since at this point we don't know if parentChain is a built-in chain, do both.
StringAppendF(&command, ":%s -\n", parentChain);
StringAppendF(&command,