关闭

Iptables小结

标签: iptables防火墙网络linux
671人阅读 评论(0) 收藏 举报
分类:

转载请标明出处:http://blog.csdn.net/EdisonChang/article/details/52372701

这篇文章是对近期学习Iptables的一些小结,博文参考到一些网络上的资料,包括一些名称定义都是在各类文章中摘抄的,先推荐几篇文章。

iptables规则配置 增加、删除和修改命令
iptables详解
Linux防火墙iptables学习笔记(一)入门要领
Linux防火墙iptables学习笔记(二)参数指令
…..
Linux防火墙iptables学习笔记(五)linux+iptables构筑防火墙实例
Android基于Iptables的app网络访问控制讲解

相信感兴趣的朋友,通过ubuntuer 关于Linux 防火墙Iptables的这几篇文章的介绍,对Iptables也基本了解了。

Iptables是什么?

Iptables可以称为是linux中的防火墙,Iptables的前身叫Ipfirewall (内核1.x时代),到了内核2.x系列,软件更名为Ipchains,可以将规则组成一个列表,实现数据的访问控制功能。

他们都是工作在用户空间中,定义规则的工具,本身并不算是防火墙。它们定义的规则,可以让在内核空间当中的netfilter来读取,并且实现让防火墙工作。而放入内核的地方必须要是特定的位置,必须是tcp/ip的协议栈经过的地方。而这个tcp/ip协议栈必须经过的地方,可以实现读取规则的地方就叫做
netfilter.(网络过滤器)

作者一共在内核空间中选择了5个位置,
1.内核空间中:从一个网络接口进来,到另一个网络接口去的
2.数据包从内核流入用户空间的
3.数据包从用户空间流出的
4.进入/离开本机的外网接口
5.进入/离开本机的内网接口

这五个位置也被称为五个钩子函数(hook functions),也叫五个规则链。
1.PREROUTING (路由前)
2.INPUT (数据包流入口)
3.FORWARD (转发管卡)
4.OUTPUT(数据包出口)
5.POSTROUTING(路由后)
这是NetFilter规定的五个规则链,任何一个数据包,只要经过本机,必将经过这五个链中的其中一个链。

Iptables定义规则的方式
格式:iptables [-t table] COMMAND chain CRETIRIA -j ACTION
-t table :3个filter nat mangle
COMMAND:定义如何对规则进行管理
chain:指定你接下来的规则到底是在哪个链上操作的,当定义策略的时候,是可以省略的
CRETIRIA:指定匹配标准
-j ACTION :指定如何进行处理

其他的命令参数列表在 Linux防火墙iptables学习笔记(二)参数指令 中有很详细的介绍,感兴趣的朋友可以到文中阅读。

Android 应用中如何使用?
在root过的Android设备上,通过shell,可以创建或者修改Iptables命令链,所以利用Iptables 可以针对不同的app、不同的域名配置不同的网络访问控制策略(允许访问/禁止访问)。

举个栗子,譬如需要限制应用A(包名:com.example.A)访问网络,Iptables规则是通过uid来区分应用,所以首先获取应用A的uid。关于uid我在换肤系列的博文中也提到过,Android系统在安装apk时会为应用分配一个uid,uid在此设备上将唯一且不再变化。但不同设备的uid是不一样的,应用也可以通过在AndroidManifest.xml中通过android:shareUserId字段来和其他应用共享uid,一旦共享了uid即实现应用间的资源共享。

        try {
            PackageManager pm = getPackageManager();
            ApplicationInfo info = pm.getApplicationInfo("com.example.A", PackageManager.GET_ACTIVITIES);
            Log.d("test", "uid" + info.uid);
        } catch (NameNotFoundException e) {
            e.printStackTrace();
        }

接下去就是创建规则并关联到应用A,

String argsOut[], argsIn[];
                        argsOut = new String[]{"-A", "OUTPUT", "-m", "owner", "--uid-owner", String.valueOf(uid), "-j", "DROP"};
                        argsIn = new String[]{"-A", "INPUT", "-m", "owner", "--uid-owner", String.valueOf(uid), "-j", "DROP"};
                        exec("iptables", argsOut, 5000);
                        exec("iptables", argsIn, 5000);

添加完规则后,可以通过 iptables -L 查看规则是否创建成功。
以下的代码是实现iptables 规则查询,如果发现应用自己被DROP就删除IpTables规则,实现网络诊断恢复。

 private static String exec(String cmd, String args[], int timeOut) {
        try {
            String arg = "";
                if (args != null) {
                    for (String s : args) {
                        arg += " ";
                        arg += s;
                    }
                }
                return CommandOutput(cmd + arg);
        } catch (Throwable e) {
            throw new AndroidRuntimeException("Root service has not run");
        }
    }

    private static String CommandOutput(String cmd) throws Exception {
        Process p = Runtime.getRuntime().exec("su");
        DataOutputStream os = new DataOutputStream(p.getOutputStream());
        InputStream is = p.getInputStream();
        String result = null;
        os.writeBytes(cmd + "\n");
        int readed = 0;
        byte[] buff = new byte[4096];
        int count = 0;
        while (is.available() <= 0 && count < 4) {
            try {
                count++;
                Thread.sleep(2000);
            } catch (Exception ex) {
            }
        }

        while (is.available() > 0) {
            readed = is.read(buff);
            if (readed <= 0) break;
            String seg = new String(buff, 0, readed);
            result = seg;
        }
        os.writeBytes("exit\n");
        os.flush();
        return result;
    }

    public static void execIpTables() {
        PriorityThreadFactory.newThread(TAG, new Runnable() {
            @Override
            public void run() {
                String iptables;
                try {
                    LogUtils.i(TAG, "iptables -L");

                    String args[];
                    args = new String[]{"-L"};
                    iptables = exec("iptables", args, 10000);

                    int rules = 0;
                    int uid = android.os.Process.myUid();
                    rules = getDropRules(uid, iptables);
                    for (int j = 0; j < rules; j++) {
                        String argsOut[], argsIn[];
                        argsOut = new String[]{"-D", "OUTPUT", "-m", "owner", "--uid-owner", String.valueOf(uid), "-j", "DROP"};
                        argsIn = new String[]{"-D", "INPUT", "-m", "owner", "--uid-owner", String.valueOf(uid), "-j", "DROP"};
                        exec("iptables", argsOut, 5000);
                        exec("iptables", argsIn, 5000);
                    }

                    String arg2s[];
                    arg2s = new String[]{"--line-numbers", "-L", "OUTPUT"};
                    iptables = exec("iptables", arg2s, 10000);

                    List<Integer> lineNum = getDropRuleLines(uid, iptables);
                    for (int j = 0; j < lineNum.size(); j++) {
                        String argsOut[];
                        argsOut = new String[]{"-D", "OUTPUT", String.valueOf(lineNum.get(j))};
                        exec("iptables", argsOut, 5000);
                    }

                    String arg3s[];
                    arg3s = new String[]{"--line-numbers", "-L", "INPUT"};
                    iptables = exec("iptables", arg3s, 10000);

                    List<Integer> lineNum2 = getDropRuleLines(uid, iptables);
                    for (int j = 0; j < lineNum2.size(); j++) {
                        String argsOut[];
                        argsOut = new String[]{"-D", "INPUT", String.valueOf(lineNum2.get(j))};
                        exec("iptables", argsOut, 5000);
                    }

                } catch (Throwable e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

    private static int getDropRules(int uid, String iptables) {

        if (TextUtils.isEmpty(iptables)) {
            return 0;
        }

        String[] ipTableArray = iptables.split("\n");
        String uidFormat = String.format("u0_a" + uid % 1000);
        int count = 0;
        for (String ipTable : ipTableArray) {
            if (ipTable.startsWith("DROP") && ipTable.contains(uidFormat)) {
                ++count;
            }
        }
        LogUtils.i(TAG, "getDropRules uid = " + uid + " count = " + count);
        return count;
    }

    private static List<Integer> getDropRuleLines(int uid, String iptables) {

        List<Integer> lineNum = new ArrayList<>();
        if (TextUtils.isEmpty(iptables)) {
            return lineNum;
        }

        String[] ipTableArray = iptables.split("\n");
        String uidFormat = String.format("u0_a" + uid % 1000);
        for (int i = 0; i < ipTableArray.length; i++) {
            if (ipTableArray[i].contains("DROP") && ipTableArray[i].contains(uidFormat)) {
                String[] segment = ipTableArray[i].split(" ");
                try {
                    lineNum.add(Integer.valueOf(segment[0]));
                } catch (NumberFormatException e) {
                    lineNum.add(i);
                }
            }
        }
        LogUtils.i(TAG, "getDropRules uid = " + uid + " count = " + lineNum.size());
        return lineNum;
    }

Iptables是一个非常重要的工具,对其初步了解已经足够体会到它的强大,源码下载。文章就先写到这里,欢迎指正。

1
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:31202次
    • 积分:680
    • 等级:
    • 排名:千里之外
    • 原创:20篇
    • 转载:2篇
    • 译文:0篇
    • 评论:13条
    文章分类
    最新评论