android 限制浏览器等应用访问某个网站

前言

最近有个需求,就是需要在服务器后台动态的禁止android 手机访问某些网址。

一般来说,像禁止访问某些网址这个需求,我们会在公司的PC 端见过,例如公司内网可能访问不了一些云盘之类的网站。这些要么是it在PC 端动了手脚,要么是直接将连接的网络进行了某种过滤操作导致。

拿到这个需求的时候。我心里想到了以下两种方法:

1.通过android 源码,追http 网络请求,在请求处选择性的禁止屏蔽某些网络访问。
2.使用android 原生提供的iptables。网络防火墙。

最后选择使用后者,iptables 来实现。毕竟人家都已经实现了,光拿来用就好了。

1.开始实现

命令测试

至于什么是iptables 。大家可以网上搜一搜。这里就不在赘述了。iptables 的命令这里也不再详细说了。这里主要说下我使用iptables 踩过的坑和遇到的问题,以及最后将问题迎刃而解的过程。

我直接在shell 命令行,通过命令执行iptables 测试,以上需求,验证是可行的。

首先  iptables -nvL   可以列出所有的规则
iptables -t filter -I INPUT -s 39.106.226.142 -j ACCEPT(允许访问39.106.226.142 网址)
iptables -t filter -I INPUT -s 39.106.226.142 -j REJECT(拒绝访问39.106.226.142 网址)

注:39.106.226.142 ip 对应的CSDN 网址的ip,如果想要禁止其他的网址,可以在PC 端ping 一下对应网址,就会看到其ip。不过后面我才知道,iptables 是支持直接过滤url 的。但是我测试没成功。先暂且绕一下路,先把网址转换为ip 吧。(某些大型网站,一个域名会对应好多ip,所以,能用url 过滤,最好还是用url 过滤)

在shell 命令行执行以上命令后,再通过iptables -nvL 就可以看到我们禁止的网址被加入到iptables 规则中了。此时也已经生效了。我们的手机已经没有办法再响应39.106.226.142(CSDN)网址了。任何浏览器访问此网址都不行。

再分享一个命令 iptables -F 清除掉所有规则。

还要再说一点:网上查资料,iptables 共有INPUT,等几个链,但是用户也是可以自定义链的,光自定义一个链还不行,还需要将自定义的链与系统提供的原始链关联起来,否则在自定义链里面放任何规则都是不生效的。

在这里插入图片描述

2.代码执行命令

通过以上在shell 行输入命令的方式,验证可行,接下来就是要用代码去执行这些命令了。接下来问题就来了。

首先,用代码去执行命令,我们首先会想到 **Runtime.getRuntime().exec();**或者用以下的方法去执行

 /* 
     * args[0] : shell 命令  如"ls" 或"ls -1"; 
     * args[1] : 命令执行路径  如"/" ; 
     */
    public static String execute(String[] cmmand, String directory) throws IOException
    {
        String result = "";
        try
        {
            ProcessBuilder builder = new ProcessBuilder(cmmand);
            if (directory != null)
            {
                builder.directory(new File(directory));
            }

            builder.redirectErrorStream(true);
            Process process = builder.start();
            InputStream is = process.getInputStream();
            byte[] buffer = new byte[256];

            int readlen = 0;
            while ((readlen = is.read(buffer)) != -1)
            {
                byte[] str = new byte[readlen];
                for (int i = 0; i < readlen; i++)
                {
                    str[i] = buffer[i];
                }
                result = result + new String(str);
            }
            is.close();
        } catch (Exception e)
        {
            e.printStackTrace();
        }
        return result.substring(0, result.length() - 1);
    }

    public static List<String> newExecCmd(String[] arr)
    {
        List<String> result = null;
        Process proc = null;
        try
        {
            proc = Runtime.getRuntime().exec("/system/bin/sh", null, new File("/system/bin")); // android中使�?
        } catch (IOException e)
        {
            e.printStackTrace();
        }
        if (proc != null)
        {
            BufferedReader in = new BufferedReader(new InputStreamReader(proc.getInputStream()));
            PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(
                    proc.getOutputStream())), true);
            result = new ArrayList<String>();
            for (int i = 0; i < arr.length; i++)
            {
                out.println(arr[i]);
            }
            out.println("exit");
            try
            {
                String line;
                while ((line = in.readLine()) != null)
                {
                    result.add(line);
                }
                // proc.waitFor(); //上面读这个流是阻塞的,所以waitfor 没太大必要�?
                in.close();
                out.close();
                proc.destroy();
            } catch (Exception e)
            {
                e.printStackTrace();
            }
        }
        return result;
    }

但是使用后,并没有什么卵用,我起初看log 中有avc 的提示,以为是selinux 的问题,没想到关掉selinux 的权限后,也没效果。我这条命令是在系统应用中执行的,权限我应该很大的。所以应该也不是应用的权限问题。

我甚至写了个jni,在c中调用也不行。

3.C 直接调用

最后,说实话,我也没找到原因。应该还是权限的问题。这个iptables 命令,只能在底层执行。所以,就要从上层调用底层,换句话说,也就是底层要提供接口给上层调用。于是乎,我就在源码里面搜索与iptables 有关的代码。还真的搜索了(这里是MTK 封装实现的,是通过hidl 调用的)。

1. 底层执行iptables 命令

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2. 接口封装

在这里插入图片描述

3.应用调用

在这里插入图片描述

这样就可以将上层用户想要设置的命令执行成功。不过这个iptables 只一次生效。如果机器重启,则规则失效。是需要重新设置的。建议将需要的规则写在sh 脚本里面。然后在开机的时候重新执行下。像下面这样。

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

假装多好123

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值