netd
概述
Netd 是 Android 系统中专门负责网络管理和控制的后台守护程序,其功能主要分为三个部分
- 设置防火墙(Firewall) 、网络地址转换(NAT) 、带宽控制 、无线网卡软接入点控制(Soft Access Ponit)控制,网络设备绑定等等
- Android 系统中 DNS 信息的缓存和管理
- 网络服务搜索功能(Net Service Discovery, 简称NSD)功能,包括服务注册(Service Registration) 、服务搜索(Service Browse)和服务名解析(Service Resolve)等
Netd 的工作流程分为两个部分:
- 接收并处理来自Framework层中的NetworkManagementService或者NsdService的命令。这些命令最终由Netd中对应的Command去处理
- 接收并解析来自Kernel的UEvent消息,然后转发给Framework层对应的Service去处理
源码
tree system/netd
├── Android.mk
├── client
│ ├── Android.mk
│ ├── FwmarkClient.cpp
│ ├── FwmarkClient.h
│ └── NetdClient.cpp
├── include
│ ├── FwmarkCommand.h
│ ├── Fwmark.h
│ ├── NetdClient.h
│ ├── Permission.h
│ └── Stopwatch.h
├── MODULE_LICENSE_APACHE2
├── NOTICE
├── server
│ ├── Android.mk
│ ├── BandwidthController.cpp
│ ├── BandwidthController.h
│ ├── BandwidthControllerTest.cpp
│ ├── binder
│ │ └── android
│ │ └── net
│ │ ├── INetd.aidl
│ │ ├── metrics
│ │ │ └── INetdEventListener.aidl
│ │ ├── UidRange.aidl
│ │ ├── UidRange.cpp
│ │ └── UidRange.h
│ ├── ClatdController.cpp
│ ├── ClatdController.h
│ ├── CleanSpec.mk
│ ├── CommandListener.cpp
│ ├── CommandListener.h
│ ├── ConnmarkFlags.h
│ ├── Controllers.cpp
│ ├── Controllers.h
│ ├── DnsProxyListener.cpp
│ ├── DnsProxyListener.h
│ ├── DummyNetwork.cpp
│ ├── DummyNetwork.h
│ ├── DumpWriter.cpp
│ ├── DumpWriter.h
│ ├── EventReporter.cpp
│ ├── EventReporter.h
│ ├── FirewallController.cpp
│ ├── FirewallController.h
│ ├── FirewallControllerTest.cpp
│ ├── FwmarkServer.cpp
│ ├── FwmarkServer.h
│ ├── IdletimerController.cpp
│ ├── IdletimerController.h
│ ├── InterfaceController.cpp
│ ├── InterfaceController.h
│ ├── IptablesBaseTest.cpp
│ ├── IptablesBaseTest.h
│ ├── LocalNetwork.cpp
│ ├── LocalNetwork.h
│ ├── main.cpp
│ ├── MDnsSdListener.cpp
│ ├── MDnsSdListener.h
│ ├── NatController.cpp
│ ├── NatController.h
│ ├── NatControllerTest.cpp
│ ├── ndc.c
│ ├── NetdCommand.cpp
│ ├── NetdCommand.h
│ ├── NetdConstants.cpp
│ ├── NetdConstants.h
│ ├── NetdNativeService.cpp
│ ├── NetdNativeService.h
│ ├── netd.rc
│ ├── NetlinkHandler.cpp
│ ├── NetlinkHandler.h
│ ├── NetlinkManager.cpp
│ ├── NetlinkManager.h
│ ├── NetworkController.cpp
│ ├── NetworkController.h
│ ├── Network.cpp
│ ├── Network.h
│ ├── oem_iptables_hook.cpp
│ ├── oem_iptables_hook.h
│ ├── PhysicalNetwork.cpp
│ ├── PhysicalNetwork.h
│ ├── PppController.cpp
│ ├── PppController.h
│ ├── QtiConnectivityAdapter.cpp
│ ├── QtiConnectivityAdapter.h
│ ├── QtiDataController.cpp
│ ├── QtiDataController.h
│ ├── ResolverController.cpp
│ ├── ResolverController.h
│ ├── ResolverStats.h
│ ├── ResponseCode.h
│ ├── RouteController.cpp
│ ├── RouteController.h
│ ├── SockDiag.cpp
│ ├── SockDiag.h
│ ├── SockDiagTest.cpp
│ ├── SoftapController.cpp
│ ├── SoftapController.h
│ ├── StrictController.cpp
│ ├── StrictController.h
│ ├── StrictControllerTest.cpp
│ ├── TetherController.cpp
│ ├── TetherController.h
│ ├── UidRanges.cpp
│ ├── UidRanges.h
│ ├── VirtualNetwork.cpp
│ └── VirtualNetwork.h
└── tests
├── Android.mk
├── benchmarks
│ ├── Android.mk
│ ├── connect_benchmark.cpp
│ ├── dns_benchmark.cpp
│ └── main.cpp
├── binder_test.cpp
├── dns_responder
│ ├── Android.mk
│ ├── dns_responder_client.cpp
│ ├── dns_responder_client.h
│ ├── dns_responder.cpp
│ └── dns_responder.h
├── netd_integration_test.cpp
└── netd_test.cpp
socket
system/netd/server/netd.rc
service netd /system/bin/netd
class main
socket netd stream 0660 root system
socket dnsproxyd stream 0660 root inet
socket mdns stream 0660 root system
socket fwmarkd stream 0660 root inet
- Framework 层中 NetworkManagementService和NsdService将分别和”netd”及”mdns”建立链接并交互
- 每一个调用域名解析socket API的进程都会借由”dnsproxyd”监听socket与Netd建立链接
netstat -apn | grep netd
Active UNIX domain sockets (servers and established)
Proto RefCnt Flags Type State I-Node PID/Program Name Path
unix 2 [ ACC ] STREAM LISTENING 13121 770/netd /dev/socket/netd
unix 2 [ ACC ] STREAM LISTENING 13126 770/netd /dev/socket/dnsproxyd
unix 2 [ ACC ] STREAM LISTENING 13129 770/netd /dev/socket/mdns
unix 2 [ ACC ] STREAM LISTENING 13132 770/netd /dev/socket/fwmarkd
unix 3 [ ] STREAM CONNECTED 22795 770/netd /dev/socket/mdns
unix 3 [ ] STREAM CONNECTED 21159 770/netd
unix 2 [ ] DGRAM 13174 770/netd
unix 3 [ ] STREAM CONNECTED 22773 770/netd /dev/socket/netd
unix 3 [ ] STREAM CONNECTED 21160 770/netd
main.cpp
int main() {
using android::net::gCtls;
ALOGI("Netd 1.0 starting");
remove_pid_file();
blockSigpipe();
NetlinkManager *nm = NetlinkManager::Instance();
if (nm == nullptr) {
ALOGE("Unable to create NetlinkManager");
exit(1);
};
gCtls = new android::net::Controllers();
-------------------netd socket--------------------
CommandListener cl;
nm->setBroadcaster((SocketListener *) &cl);
if (nm->start()) {
ALOGE("Unable to start NetlinkManager (%s)", strerror(errno));
exit(1);
}
-------------------dnsproxyd socket------------------------------
// Set local DNS mode, to prevent bionic from proxying
// back to this service, recursively.
setenv("ANDROID_DNS_MODE", "local", 1);
DnsProxyListener dpl(&gCtls->netCtrl, &gCtls->eventReporter);
if (dpl.startListener()) {
ALOGE("Unable to start DnsProxyListener (%s)", strerror(errno));
exit(1);
}
-------------------mdns socket-------------------------------------
MDnsSdListener mdnsl;
if (mdnsl.startListener()) {
ALOGE("Unable to start MDnsSdListener (%s)", strerror(errno));
exit(1);
}
-------------------fwmarkd socket-----------------------------------
FwmarkServer fwmarkServer(&gCtls->netCtrl, &gCtls->eventReporter);
if (fwmarkServer.startListener()) {
ALOGE("Unable to start FwmarkServer (%s)", strerror(errno));
exit(1);
}
status_t ret;
if ((ret = NetdNativeService::start()) != android::OK) {
ALOGE("Unable to start NetdNativeService: %d", ret);
exit(1);
}
/*
* Now that we're up, we can respond to commands. Starting the listener also tells
* NetworkManagementService that we are up and that our binder interface is ready.
*/
if (cl.startListener()) {
ALOGE("Unable to start CommandListener (%s)", strerror(errno));
exit(1);
}
write_pid_file();
IPCThreadState::self()->joinThreadPool();
ALOGI("Netd exiting");
remove_pid_file();
exit(0);
}
- NetlinkManager: 接收并处理来自Kernel的UEvent消息。这些消息经NetlinkManager解析后将借助它的Broadcaster(CommandListener) 发送给Framework层的NetworkManagementService
- CommandListener: 创建netd socket, 处理来自客户端的命令
- DnsProxyListener: dnsproxyd socket
- MDnsSdListener: mdns socket
- FwmarkServer: fwmarkd socket
NetlinkManager.cpp(NM)
主要负责接收并解析来自Kernel的UEvent消息
int NetlinkManager::start() {
if ((mUeventHandler = setupSocket(&mUeventSock, NETLINK_KOBJECT_UEVENT,
0xffffffff, NetlinkListener::NETLINK_FORMAT_ASCII, false)) == NULL) {
return -1;
}
if ((mRouteHandler = setupSocket(&mRouteSock, NETLINK_ROUTE,
RTMGRP_LINK |
RTMGRP_IPV4_IFADDR |
RTMGRP_IPV6_IFADDR |
RTMGRP_IPV6_ROUTE |
(1 << (RTNLGRP_ND_USEROPT - 1)),
NetlinkListener::NETLINK_FORMAT_BINARY, false)) == NULL) {
return -1;
}
if ((mQuotaHandler = setupSocket(&mQuotaSock, NETLINK_NFLOG,
NFLOG_QUOTA_GROUP, NetlinkListener::NETLINK_FORMAT_BINARY, false)) == NULL) {
ALOGW("Unable to open qlog quota socket, check if xt_quota2 can send via UeventHandler");
// TODO: return -1 once the emulator gets a new kernel.
}
if ((mStrictHandler = setupSocket(&mStrictSock, NETLINK_NETFILTER,
0, NetlinkListener::NETLINK_FORMAT_BINARY_UNICAST, true)) == NULL) {
ALOGE("Unable to open strict socket");
// TODO: return -1 once the emulator gets a new kernel.
}
return 0;
}
-
NETLINK_KOBJECT_UEVENT: 代表kobject事件,这些事件包含的信息格式是NETLINK_FORMAT_ASCII,表示使用字符串解析的方式解析UEvent消息。 kobject一般用于通知内核中某个模块的加载和卸载。对NM来说关注的是 sys/class/net 下模块的加载和卸载消息
-
NETLINK_ROUTE: 代表kernel中routing或者link改变时对应的消息。消息内容格式为NETLINK_FORMAT_BINARY
-
NETLINK_NFLOG: 和带宽控制有关, netd中的带宽控制可以设置一个预警值,当网络数据超过一定字节数时就会触发kernel发送一个警告
-
NETLINK_NETFILTER: Netfilter 利用一些封包过滤的规则设定, 来定义出什么数据包可以接收, 什么数据包需要剔除,位于内核层。 iptables 通过命令的方式对 Netfilter 规则进行排序与修改, 位于用户层
NetlinkHandler.cpp
void NetlinkHandler::onEvent(NetlinkEvent *evt) {
if (!strcmp(subsys, "net")) { // NETLINK_KOBJECT_UEVENT、NETLINK_ROUTE
--------------------------------------------------
if (action == NetlinkEvent::Action::kAdd) {
notifyInterfaceAdded(iface);
} else if (action == NetlinkEvent::Action::kRemove) {
notifyInterfaceRemoved(iface);
}
---------------------------------------------------
} else if (!strcmp(subsys, "qlog")
|| !strcmp(subsys, "xt_quota2")) { // NETLINK_NFLOG
const char *alertName = evt->findParam("ALERT_NAME");
const char *iface = evt->findParam("INTERFACE");
notifyQuotaLimitReached(alertName, iface); // 流量预警通知
} else if (!strcmp(subsys, "strict")) { // NETLINK_NETFILTER
const char *uid = evt->findParam("UID");
const char *hex = evt->findParam("HEX");
notifyStrictCleartext(uid, hex);
} else if (!strcmp(subsys, "xt_idletimer")) { // 用于跟踪某个NIC的工作状态,即是"idle"还是"active"
const char *label = evt->findParam("INTERFACE");
const char *state = evt->findParam("STATE");
const char *timestamp = evt->findParam("TIME_NS");
const char *uid = evt->findParam("UID");
if (state)
notifyInterfaceClassActivity(label, !strcmp("active", state),
timestamp, uid);
}
}
void NetlinkHandler::notify(int code, const char *format, ...) {
char *msg;
va_list args;
va_start(args, format);
if (vasprintf(&msg, format, args) >= 0) {
mNm->getBroadcaster()->sendBroadcast(code, msg, false); // 发送给 Framework 层的 NetworkManagerService
free(msg);
} else {
SLOGE("Failed to send notification: vasprintf: %s", strerror(errno));
}
va_end(args);
}
void NetlinkHandler::notifyStrictCleartext(const char* uid, const char* hex) {
notify(ResponseCode::StrictCleartext, "%s %s", uid, hex);
}
CommandListener.cpp(CL)
主要作用是接收来自Framework的NetworkManagementService的命令
void CommandListener::registerLockingCmd(FrameworkCommand *cmd, android::RWLock& lock) {
registerCmd(new LockingFrameworkCommand(cmd, lock));
}
CommandListener::CommandListener() :
FrameworkListener("netd", true) {
registerLockingCmd(new InterfaceCmd());
registerLockingCmd(new IpFwdCmd());
registerLockingCmd(new TetherCmd());
registerLockingCmd(new NatCmd());
registerLockingCmd(new ListTtysCmd());
registerLockingCmd(new PppdCmd());
registerLockingCmd(new SoftapCmd());
registerLockingCmd(new BandwidthControlCmd(), gCtls->bandwidthCtrl.lock);
registerLockingCmd(new IdletimerControlCmd());
registerLockingCmd(new ResolverCmd());
registerLockingCmd(new FirewallCmd(), gCtls->firewallCtrl.lock);
registerLockingCmd(new ClatdCmd());
registerLockingCmd(new NetworkCommand());
registerLockingCmd(new StrictCmd());
registerLockingCmd(getQtiConnectivityCmd(this));
initializeDataControllerLib();
/*
* 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 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", "FORWARD", MANGLE_FORWARD);
createChildChains(V4, "nat", "PREROUTING", NAT_PREROUTING);
createChildChains(V4, "nat", "POSTROUTING", NAT_POSTROUTING);
// Let each module setup their child chains
setupOemIptablesHook();
/* When enabled, DROPs all packets except those matching rules. */
gCtls->firewallCtrl.setupIptablesHooks();
/* Does DROPs in FORWARD by default */
gCtls->natCtrl.setupIptablesHooks();
/*
* Does REJECT in INPUT, OUTPUT. Does counting also.
* No DROP/REJECT allowed later in netfilter-flow hook order.
*/
gCtls->bandwidthCtrl.setupIptablesHooks();
/*
* Counts in nat: PREROUTING, POSTROUTING.
* No DROP/REJECT allowed later in netfilter-flow hook order.
*/
gCtls->idletimerCtrl.setupIptablesHooks();
gCtls->bandwidthCtrl.enableBandwidthControl(false);
if (int ret = RouteController::Init(NetworkController::LOCAL_NET_ID)) {
ALOGE("failed to initialize RouteController (%s)", strerror(-ret));
}
}
假设Client端发送的命令名是”nat”,当CL收到这个命令后,首先会从其构造函数中注册的那些命令对象中找到对应该名字(即”nat”)的命令对象, 其结果就是图中的NatCmd对象。而该命令最终的处理工作将由此NatCmd对象的runCommand函数完成
ndc命令
ndc monitor
// 关闭wifi
130|L2K:/ # ndc monitor
[Connected to Netd]
614 Address removed 10.10.167.12/20 wlan0 128 0
616 Route removed fe80::/64 dev wlan0
614 Address removed fe80::20a:f5ff:fe05:888/64 wlan0 128 253
600 Iface linkstate wlan0 down
600 Iface linkstate wlan0 down
600 Iface linkstate wlan0 down
613 IfaceClass active 0 2316907674321 0
600 Iface linkstate rmnet_data0 up
616 Route updated fe80::/64 dev rmnet_data0
614 Address updated fe80::e14:e07f:1b23:67a5/64 rmnet_data0 196 253
600 Iface linkstate wlan0 down
614 Address updated 10.154.101.251/29 rmnet_data0 128 0
614 Address updated fe80::e14:e07f:1b23:67a5/64 rmnet_data0 128 253
600 Iface linkstate p2p0 down
600 Iface linkstate p2p0 down
600 Iface linkstate wlan0 down
600 Iface removed wlan0
600 Iface removed p2p0
Iptables
iptables –list
Chain INPUT (policy ACCEPT)
target prot opt source destination
REJECT all -- anywhere anywhere owner UID match u0_a88 reject-with icmp-port-unreachable
REJECT all -- anywhere anywhere owner UID match u0_a88 reject-with icmp-port-unreachable
bw_INPUT all -- anywhere anywhere
fw_INPUT all -- anywhere anywhere
Chain FORWARD (policy ACCEPT)
target prot opt source destination
oem_fwd all -- anywhere anywhere
fw_FORWARD all -- anywhere anywhere
bw_FORWARD all -- anywhere anywhere
natctrl_FORWARD all -- anywhere anywhere
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
REJECT all -- anywhere anywhere owner UID match u0_a88 reject-with icmp-port-unreachable
REJECT all -- anywhere anywhere owner UID match u0_a88 reject-with icmp-port-unreachable
oem_out all -- anywhere anywhere
fw_OUTPUT all -- anywhere anywhere
st_OUTPUT all -- anywhere anywhere
bw_OUTPUT all -- anywhere anywhere
blacklist-mms all -- anywhere anywhere
Chain blacklist-mms (1 references)
target prot opt source destination
DROP all -- anywhere 10.0.0.200 owner UID match u0_a88
DROP all -- anywhere 10.0.0.172 owner UID match u0_a88
DROP all -- anywhere 10.0.0.200 owner UID match system
DROP all -- anywhere 10.0.0.172 owner UID match system
DROP all -- anywhere 10.0.0.200 owner UID match u0_a84
DROP all -- anywhere 10.0.0.172 owner UID match u0_a84
DROP all -- anywhere 10.0.0.200 owner UID match u0_a89
DROP all -- anywhere 10.0.0.172 owner UID match u0_a89
DROP all -- anywhere 10.0.0.200 owner UID match u0_a90
DROP all -- anywhere 10.0.0.172 owner UID match u0_a90
DROP all -- anywhere 10.0.0.200 owner UID match u0_a91
DROP all -- anywhere 10.0.0.172 owner UID match u0_a91
Chain bw_FORWARD (1 references)
target prot opt source destination
Chain bw_INPUT (1 references)
target prot opt source destination
all -- anywhere anywhere ! quota globalAlert: 2097152 bytes
all -- anywhere anywhere owner socket exists
Chain bw_OUTPUT (1 references)
target prot opt source destination
all -- anywhere anywhere ! quota globalAlert: 2097152 bytes
all -- anywhere anywhere owner socket exists
Chain bw_costly_shared (0 references)
target prot opt source destination
bw_penalty_box all -- anywhere anywhere
Chain bw_data_saver (1 references)
target prot opt source destination
RETURN all -- anywhere anywhere
Chain bw_happy_box (1 references)
target prot opt source destination
RETURN all -- anywhere anywhere owner UID match u0_a8
RETURN all -- anywhere anywhere owner UID match u0_a29
RETURN all -- anywhere anywhere owner UID match 0-9999
bw_data_saver all -- anywhere anywhere
Chain bw_penalty_box (1 references)
target prot opt source destination
bw_happy_box all -- anywhere anywhere
Chain fw_FORWARD (1 references)
target prot opt source destination
Chain fw_INPUT (1 references)
target prot opt source destination
Chain fw_OUTPUT (1 references)
target prot opt source destination
Chain fw_dozable (0 references)
target prot opt source destination
RETURN all -- anywhere anywhere
RETURN tcp -- anywhere anywhere tcp flags:RST/RST
RETURN all -- anywhere anywhere owner UID match 0-9999
DROP all -- anywhere anywhere
Chain fw_powersave (0 references)
target prot opt source destination
RETURN all -- anywhere anywhere
RETURN tcp -- anywhere anywhere tcp flags:RST/RST
RETURN all -- anywhere anywhere owner UID match 0-9999
DROP all -- anywhere anywhere
Chain fw_standby (0 references)
target prot opt source destination
RETURN all -- anywhere anywhere
RETURN tcp -- anywhere anywhere tcp flags:RST/RST
Chain natctrl_FORWARD (1 references)
target prot opt source destination
DROP all -- anywhere anywhere
Chain natctrl_tether_counters (0 references)
target prot opt source destination
Chain oem_fwd (1 references)
target prot opt source destination
Chain oem_out (1 references)
target prot opt source destination
Chain st_OUTPUT (1 references)
target prot opt source destination
Chain st_clear_caught (2 references)
target prot opt source destination
Chain st_clear_detect (0 references)
target prot opt source destination
REJECT all -- anywhere anywhere connmark match 0x2000000/0x2000000 reject-with icmp-port-unreachable
RETURN all -- anywhere anywhere connmark match 0x1000000/0x1000000
CONNMARK tcp -- anywhere anywhere u32 "0x0>>0x16&0x3c@0xc>>0x1a&0x3c@0x0&0xffff0000=0x16030000&&0x0>>0x16&0x3c@0xc>>0x1a&0x3c@0x4&0xff0000=0x10000" CONNMARK or 0x1000000
CONNMARK udp -- anywhere anywhere u32 "0x0>>0x16&0x3c@0x8&0xffff0000=0x16fe0000&&0x0>>0x16&0x3c@0x14&0xff0000=0x10000" CONNMARK or 0x1000000
RETURN all -- anywhere anywhere connmark match 0x1000000/0x1000000
st_clear_caught tcp -- anywhere anywhere state ESTABLISHED u32 "0x0>>0x16&0x3c@0xc>>0x1a&0x3c@0x0&0x0=0x0"
st_clear_caught udp -- anywhere anywhere
Chain st_penalty_log (0 references)
target prot opt source destination
CONNMARK all -- anywhere anywhere CONNMARK or 0x1000000
NFLOG all -- anywhere anywhere
Chain st_penalty_reject (0 references)
target prot opt source destination
CONNMARK all -- anywhere anywhere CONNMARK or 0x2000000
NFLOG all -- anywhere anywhere
REJECT all -- anywhere anywhere reject-with icmp-port-unreachable
概念
iptables是Linux系统中最重要的网络管控工具。它与Kernel中的netfilter模块配合工作,其主要功能是为netfilter设置一些过滤(filter)或网络地址转换(NAT)的规则。当Kernel收到网络数据包后,将会依据iptables设置的规则进行相应的操作。举个最简单的例子,可以利用iptables设置这样一条防火墙规则:丢弃来自IP地址为192.168.1.108的所有数据包
- iptables内部(其实是Kernel的netfilter模块)维护着四个Table,分别是filter、nat、mangle和raw
- Table中定义了Chain。一个Table可以支持多个Chain,Chain实际上是Rule的集合,每个Table都有默认的Chain。例如filter表默认的Chain有INPUT、OUTPUT、FORWARD。用户可以自定义Chain,也可修改Chain中的Rule
- Rule就是iptables工作的规则。首先,系统将检查要处理的数据包是否满足Rule设置的条件,如果满足则执行Rule中设置的目标(Target),否则继续执行Chain中的下一条Rule
工作过程
- 数据包从左边进入IP协议栈,进行IP校验以后,数据包被第一个钩子函数PRE_ROUTING处理,然后就进入路由模块,由其决定该数据包是转发出去还是送给本机
- 若该数据包是送给本机的,则要经过钩子函数LOCAL_IN处理后传递给本机的上层协议
- 若该数据包应该被转发,则它将被钩子函数FORWARD处理,然后还要经钩子函数POST_ROUTING处理后才能传输到网络
- 本机进程产生的数据包要先经过钩子函数LOCAL_OUT处理后,再进行路由选择处理,然后经过钩子函数POST_ROUTING处理后再发送到网络
命令
Target
ACCEPT:接收数据包。
DROP:直接丢弃数据包。没有任何信息会反馈给数据源端。
REJECT: 直接丢弃数据包。会反馈给数据源端。
RETURN:返回到调用Chain,略过后续的Rule处理。
QUEUE:数据返回到用户空间去处理。
Action
-t:指定table。如果不带此参数,则默认为filter表。
-A,--append chain rule-specification:在指定Chain的末尾添加一条Rule,rule-specification指明该Rule的内容。
-D,--delete chain rule-specification:删除指定Chain中满足rule-specification的那条Rule。
-I,--insert chain[rule num]rule-specification:为指定Chain插入一条Rule,位置由rule num指定。如果没有该参数,则默认加到Chain-N:创建一条新Chain。
-L,--list:显示指定Table的Chain和Rule的信息。
-i:指定接收数据包的网卡名,如eth0、eth1等。
-o:指定发出数据包的网卡名。
-p:指定协议,如tcp、udp等。
-s,--source address[/mask]:指定数据包的源IP地址。
-j,--jump target:跳转到指定目标,如ACCEPT、DROP等
Demo
iptables -t filter -A INPUT -s 192.168.1.108 -j DROP
List the rules in a chain
L2K:/ # iptables -L INPUT
Chain INPUT (policy ACCEPT)
target prot opt source destination
REJECT all -- anywhere anywhere owner UID match u0_a88 reject-with icmp-port-unreachable
REJECT all -- anywhere anywhere owner UID match u0_a88 reject-with icmp-port-unreachable
bw_INPUT all -- anywhere anywhere
fw_INPUT all -- anywhere anywhere
DROP all -- 192.168.1.108 anywhere
Print the rules in a chain
L2K:/ # iptables -S INPUT
-P INPUT ACCEPT
-A INPUT -i wlan0 -m owner --uid-owner 10088 -j REJECT --reject-with icmp-port-unreachable
-A INPUT -i rmnet_data0 -m owner --uid-owner 10088 -j REJECT --reject-with icmp-port-unreachable
-A INPUT -j bw_INPUT
-A INPUT -j fw_INPUT
-A INPUT -s 192.168.1.108/32 -j DROP