Iptables in android

Are IPtables built into the Android kernel? If so, how to use them in our android application?

+24
source share
6 answers

iptables is the default module in AOSP, you can use netfilter to write c-code to handle it.

For example, you can create an android project and write a JNI file, use ndk-build to compile it, and then adb click the executable file for the Android file system to execute. And in the mobile version you can use the shell for it, directly use the iptables command as the root user, as in Linux.

investments:

#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); } 
+8
source
+17
source

I do not think iptables is available on a regular Android distribution. However, on the root phone, you can add the cross-compiled iptables binary.

+3
source

The executable file "itables" is present in the Android source code. The kernel must also support it. Although you will probably need root privileges on your device to play with it.

+1
source

This is a 5 year solution (root required):

But since Google Code has become read-only, it will continue to work as usual until β€œat least January 2016,” which means that this answer may not be useful next month.

+1
source

with the root phone, try using busybox and a terminal to run "iptables -L" to display the current tables. I found that all I needed to do was root my phone and iptables on my other retail Android. once the device confirms iptables, you can use the command line through the application to configure the tables.

0
source

Source: https://habr.com/ru/post/958477/


All Articles