IPtables 是内置在 android 内核中的吗?如果是,如何在我们的 android 应用程序中使用它们?
问问题
72912 次
6 回答
19
- iptables 在 Android 源代码分发中可用。然而,该版本仅适用于使用 Linux 内核 2.6.29 构建的设备。
- 零售 Android 设备的用户无法访问 iptables 二进制文件。甚至 Android 操作系统本身也无法访问该二进制文件。这在 Android 中是硬编码的。许多设备也根本没有 iptables。
- 访问 iptables 二进制文件的唯一方法是构建您自己的 Android 映像。查看http://randomizedsort.blogspot.com/2010/08/building-android-and-linux-kernel-for.html。一旦您对这个过程感到满意,请查看http://randomizedsort.blogspot.com/2011/03/porting-iptables-1410-to-android.html。
于 2011-03-23T18:00:32.140 回答
13
iptables 是 AOSP 中的默认模块,您可以使用 netfilter 编写 c 代码来处理它。
例如,您可以创建一个android项目,并编写一个JNI文件,使用ndk-build编译它,然后将可执行文件adb推送到android文件系统中执行。而在移动端,你可以 adb shell 到它,直接以 root 用户使用 iptables 命令,就像在 linux 中一样。
附件:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <linux/types.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/netfilter.h> /* for NF_ACCEPT */
#include <errno.h>
#include <libnetfilter_queue/libnetfilter_queue.h>
#ifdef __LITTLE_ENDIAN
#define IPQUAD(addr) \
((unsigned char *)&addr)[0], \
((unsigned char *)&addr)[1], \
((unsigned char *)&addr)[2], \
((unsigned char *)&addr)[3]
#else
#define IPQUAD(addr) \
((unsigned char *)&addr)[3], \
((unsigned char *)&addr)[2], \
((unsigned char *)&addr)[1], \
((unsigned char *)&addr)[0]
#endif
#define TO "192.168.191.129"
#define NAT_TO "192.168.2.246"
struct tcp_pseudo /*the tcp pseudo header*/
{
__u32 src_addr;
__u32 dst_addr;
__u8 zero;
__u8 proto;
__u16 length;
} pseudohead;
long checksum(unsigned short *addr, unsigned int count) {
/* Compute Internet Checksum for "count" bytes
* beginning at location "addr".
*/
register long sum = 0;
while( count > 1 ) {
/* This is the inner loop */
sum += * addr++;
count -= 2;
}
/* Add left-over byte, if any */
if( count > 0 )
sum += * (unsigned char *) addr;
/* Fold 32-bit sum to 16 bits */
while (sum>>16)
sum = (sum & 0xffff) + (sum >> 16);
return ~sum;
}
/*************************tcp checksum**********************/
long get_tcp_checksum(struct iphdr * myip, struct tcphdr * mytcp) {
__u16 total_len = ntohs(myip->tot_len);
int tcpopt_len = mytcp->doff*4 - 20;
int tcpdatalen = total_len - (mytcp->doff*4) - (myip->ihl*4);
pseudohead.src_addr=myip->saddr;
pseudohead.dst_addr=myip->daddr;
pseudohead.zero=0;
pseudohead.proto=IPPROTO_TCP;
pseudohead.length=htons(sizeof(struct tcphdr) + tcpopt_len + tcpdatalen);
int totaltcp_len = sizeof(struct tcp_pseudo) + sizeof(struct tcphdr) + tcpopt_len +tcpdatalen;
//unsigned short * tcp = new unsigned short[totaltcp_len];
unsigned short * tcp = malloc(totaltcp_len);
memcpy((unsigned char *)tcp,&pseudohead,sizeof(struct tcp_pseudo));
memcpy((unsigned char *)tcp+sizeof(struct tcp_pseudo),(unsigned char*)mytcp,sizeof(struct tcphdr));
memcpy((unsigned char *)tcp+sizeof(struct tcp_pseudo)+sizeof(struct tcphdr),(unsigned char *)myip+(myip->ihl*4)+(sizeof(struct tcphdr)), tcpopt_len);
memcpy((unsigned char *)tcp+sizeof(struct tcp_pseudo)+sizeof(struct tcphdr)+tcpopt_len, (unsigned char *)mytcp+(mytcp->doff*4), tcpdatalen);
/* printf("pseud length: %d\n",pseudohead.length);
printf("tcp hdr length: %d\n",mytcp->doff*4);
printf("tcp hdr struct length: %d\n",sizeof(struct tcphdr));
printf("tcp opt length: %d\n",tcpopt_len);
printf("tcp total+psuedo length: %d\n",totaltcp_len);
fflush(stdout);
printf("tcp data len: %d, data start %u\n", tcpdatalen,mytcp + (mytcp->doff*4));
*/
return checksum(tcp,totaltcp_len);
}
static u_int16_t tcp_checksum(struct iphdr* iphdrp){
struct tcphdr *tcphdrp =
(struct tcphdr*)((u_int8_t*)iphdrp + (iphdrp->ihl<<2));
return get_tcp_checksum(iphdrp, tcphdrp);
}
static void set_tcp_checksum(struct iphdr* iphdrp){
struct tcphdr *tcphdrp =
(struct tcphdr*)((u_int8_t*)iphdrp + (iphdrp->ihl<<2));
tcphdrp->check = 0;
tcphdrp->check = get_tcp_checksum(iphdrp, tcphdrp);
}
/****************************tcp checksum end****************************/
/********************************Ip checksum*****************************/
static u_int16_t ip_checksum(struct iphdr* iphdrp){
return checksum((unsigned short*)iphdrp, iphdrp->ihl<<2);
}
static void set_ip_checksum(struct iphdr* iphdrp){
iphdrp->check = 0;
iphdrp->check = checksum((unsigned short*)iphdrp, iphdrp->ihl<<2);
}
/****************************Ip checksum end******************************/
static int cb(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg,
struct nfq_data *nfa, void *data)
{
int id = 0;
struct nfqnl_msg_packet_hdr *ph;
int pdata_len;
unsigned char *payload;
printf("entering callback\n");
ph = nfq_get_msg_packet_hdr(nfa);
if (ph) {
id = ntohl(ph->packet_id);
}
pdata_len = nfq_get_payload(nfa, &payload);
if (pdata_len >= 0) {
struct iphdr *iphdrp = (struct iphdr*)payload;
iphdrp->daddr = inet_addr(NAT_TO);
set_ip_checksum(iphdrp);
if(iphdrp->protocol == IPPROTO_TCP){
set_tcp_checksum(iphdrp);
printf(" ipsum+ %hu tcpsum+ %hu",
ip_checksum(iphdrp), tcp_checksum(iphdrp));
}
printf("len %d iphdr %d %u.%u.%u.%u ->",
pdata_len,
iphdrp->ihl<<2,
IPQUAD(iphdrp->saddr));
printf(" %u.%u.%u.%u",
IPQUAD(iphdrp->daddr));
printf(" ipsum %hu", ip_checksum(iphdrp));
if(iphdrp->protocol == IPPROTO_TCP){
printf(" tcpsum %hu", tcp_checksum(iphdrp));
}
printf("\n");
}
return nfq_set_verdict(qh, id, NF_ACCEPT, (u_int32_t)pdata_len, payload);
}
int main(int argc, char **argv)
{
struct nfq_handle *h;
struct nfq_q_handle *qh;
struct nfnl_handle *nh;
int fd;
int rv;
char buf[4096] __attribute__ ((aligned));
printf("opening library handle\n");
h = nfq_open();
if (!h) {
fprintf(stderr, "error during nfq_open()\n");
exit(1);
}
printf("unbinding existing nf_queue handler for AF_INET (if any)\n");
if (nfq_unbind_pf(h, AF_INET) < 0) {
fprintf(stderr, "error during nfq_unbind_pf()\n");
exit(1);
}
printf("binding nfnetlink_queue as nf_queue handler for AF_INET\n");
if (nfq_bind_pf(h, AF_INET) < 0) {
fprintf(stderr, "error during nfq_bind_pf()\n");
exit(1);
}
printf("binding this socket to queue '0'\n");
qh = nfq_create_queue(h, 0, &cb, NULL);
if (!qh) {
fprintf(stderr, "error during nfq_create_queue()\n");
exit(1);
}
printf("setting copy_packet mode\n");
if (nfq_set_mode(qh, NFQNL_COPY_PACKET, 0xffff) < 0) {
fprintf(stderr, "can't set packet_copy mode\n");
exit(1);
}
fd = nfq_fd(h);
for (;;) {
if ((rv = recv(fd, buf, sizeof(buf), 0)) >= 0) {
printf("pkt received\n");
nfq_handle_packet(h, buf, rv);
continue;
}
/* if your application is too slow to digest the packets that
* are sent from kernel-space, the socket buffer that we use
* to enqueue packets may fill up returning ENOBUFS. Depending
* on your application, this error may be ignored. Please, see
* the doxygen documentation of this library on how to improve
* this situation.
*/
if (rv < 0 && errno == ENOBUFS) {
printf("losing packets!\n");
continue;
}
perror("recv failed");
break;
}
printf("unbinding from queue 0\n");
nfq_destroy_queue(qh);
#ifdef INSANE
/* normally, applications SHOULD NOT issue this command, since
* it detaches other programs/sockets from AF_INET, too ! */
printf("unbinding from AF_INET\n");
nfq_unbind_pf(h, AF_INET);
#endif
printf("closing library handle\n");
nfq_close(h);
exit(0);
}
于 2013-05-31T12:37:17.843 回答
3
我不认为 iptables 在正常的 Android 发行版中可用。但是,在有根手机上,您可以添加交叉编译的 iptables 二进制文件。
于 2011-01-02T06:55:23.877 回答
1
“itables”可执行文件存在于 Android 源代码中。内核也应该支持它。尽管您可能需要设备上的 root 权限才能使用它。
于 2011-01-17T13:41:13.587 回答
1
使用有根电话,尝试使用busybox和终端运行“iptables -L”以列出当前表。我发现我所要做的就是将我的手机 root 并在我原本零售的 android 上安装 Iptables。设备确认 iptables 后,您可以通过应用程序使用命令行来调整表格。
于 2013-10-24T06:50:49.827 回答
1
这是一个已有 5 年历史的解决方案(需要 root):
- 从http://code.google.com/p/android-wifi-tether/安装 Android WiFi Tether 的 APK
运行终端:
$ su - # mount -o remount,rw /system # cp /data/data/android.tether/bin/iptables /system/bin/
但随着谷歌代码变为只读将继续正常工作,直到“至少 2016 年 1 月”,这意味着下个月这个答案可能没用。
于 2015-12-29T13:58:27.853 回答