Android11 iptables实现网络白名单

需求

近期有一个网络白名单的需求,需要实现

  1. 用户通过输入IP/IP+端口,添加到白名单,添加后只允许白名单中的数据通行
  2. 重启后也生效
  3. 用户可进行删除,和清空

平台

基于展锐 T618 Android11

方案

android系统层通过调用iptables命令来实现

iptablesLinux系统的IP信息包过滤工具,实际就是一个Linux命令,通过这个命令,可以对整个系统发出去的包,接收到的包,以及转发的包进行拦截、修改、拒绝等操作。刚好Android也是基于Linux内核的系统,也集成了iptables,是否可以用它来限制上网行为呢?经过试验,发现是可行的。

  • 优点:能从底层限制访问某些网站,而不必在浏览器层面阻止,不仅减少了定制或修改浏览器的成本,而且控制灵活,因为能够定制各种策略;

  • 缺点:运行iptables需要root权限。

并且可以通过iptables命令查看当前的防火墙规则,具体可以百度了解一下命令

NetdNetwork Daemon 的缩写,NetdAndroid Linux KernelFramework之间通信的桥梁,表示Network守护进程。Netd负责跟一些涉及网络的配置,操作,管理,查询等相关的功能实现,比如,例如带宽控制(Bandwidth),流量统计,带宽控制,网络地址转换(NAT),个人局域网(pan),PPP链接,soft-ap,共享上网(Tether),配置路由表,interface配置管理,等等。

Framework部分通常会有一个对应的service与本地进程(如Netd)通信,并且提供API供应用层调用,轻易地找到了NetworkManagementService,在源码中位于/frameworks/base/services/java/com/android/server/NetworkManagementService.java

其中一个代码片段:

 // frameworks/base/services/core/java/com/android/server/net/NetworkManagementService.java
 @Override
 public void setFirewallEnabled(boolean enabled) {
    
    
     enforceSystemUid();
     try {
    
    
         mNetdService.firewallSetFirewallType(
                 enabled ? INetd.FIREWALL_ALLOWLIST : INetd.FIREWALL_DENYLIST);
         mFirewallEnabled = enabled;
     } catch (RemoteException | ServiceSpecificException e) {
    
    
         throw new IllegalStateException(e);
     }
 }

发现调用的是在INet接口中,在跟一根找到它的实现

 // /system/netd/server/NetdNativeService.cpp
 binder::Status NetdNativeService::firewallSetFirewallType(int32_t firewallType) {
    
    
     NETD_LOCKING_RPC(gCtls->firewallCtrl.lock, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
     auto type = static_cast<FirewallType>(firewallType);int res = gCtls->firewallCtrl.setFirewallType(type);
     return statusFromErrcode(res);
 }

 // /system/netd/server/FirewallController.cpp
 int FirewallController::setFirewallType(FirewallType ftype) {
    
    
     int res = 0;
     if (mFirewallType != ftype) {
    
    
         // flush any existing rules
         resetFirewall();if (ftype == WHITELIST) {
    
    
             // create default rule to drop all traffic
             std::string command =
                 "*filter\n"
                 "-A fw_INPUT -j DROP\n"
                 "-A fw_OUTPUT -j REJECT\n"
                 "-A fw_FORWARD -j REJECT\n"
                 "COMMIT\n";
             res = execIptablesRestore(V4V6, command.c_str());
         }// Set this after calling disableFirewall(), since it defaults to WHITELIST there
         mFirewallType = ftype;
     }
     return res ? -EREMOTEIO : 0;
 }

最后发现具体的实现都是在FirewallController.cpp中,因为我们可以加在这里,当然被调用的接口也要加上去

这里直接放个简单的流程图

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

相关类图:

在这里插入图片描述

修改流程

1.system/netd涉及修改文件
 system/netd/server/NetdNativeService.cpp
 system/netd/server/NetdNativeService.h
 system/netd/server/FirewallController.cpp
 system/netd/server/FirewallController.h
 system/netd/server/aidl_api/netd_aidl_interface/current/android/net/INetd.aidl
 system/netd/server/binder/android/net/INetd.aidl
 --------------------------------------------------
 # 以下文件或目录是自动生成或更新
 system/netd/server/Android.bp
 system/netd/server/aidl_api/netd_aidl_interface/5/

修改详细内容:

 diff --git a/server/Android.bp b/server/Android.bp
 index 2f897e5..14d567c 100644
 --- a/server/Android.bp
 +++ b/server/Android.bp
 @@ -33,6 +33,7 @@ aidl_interface {
    
    
          "2",
          "3",
          "4",
 +        "5",
      ],
  }
  
 diff --git a/server/FirewallController.cpp b/server/FirewallController.cpp
 index 3c070ce..ea2be49 100644
 --- a/server/FirewallController.cpp
 +++ b/server/FirewallController.cpp
 @@ -74,6 +74,7 @@ const char* FirewallController::LOCAL_DOZABLE = "fw_dozable";
  const char* FirewallController::LOCAL_STANDBY = "fw_standby";
  const char* FirewallController::LOCAL_POWERSAVE = "fw_powersave";
  
 +int netDrop = 0;
  // ICMPv6 types that are required for any form of IPv6 connectivity to work. Note that because the
  // fw_dozable chain is called from both INPUT and OUTPUT, this includes both packets that we need
  // to be able to send (e.g., RS, NS), and packets that we need to receive (e.g., RA, NA).
 @@ -397,5 +398,133 @@ uid_t FirewallController::discoverMaximumValidUid(const std::string& fileName) {
    
    
      return maxUid;
  }
  
 +int FirewallController::enableDNSPort(int protocol, int port) {
    
    
 +    char protocolStr[16];
 +    if(protocol == 0) {
    
    
 +        sprintf(protocolStr, "udp");
 +    } else {
    
    
 +        sprintf(protocolStr, "tcp");
 +    }
 +
 +    char portStr[16];
 +
 +    sprintf(portStr, "%d", port);
 +
 +    std::string command = Join(std::vector<std::string> {
    
    
 +        "*filter\n",
 +        StringPrintf("-I fw_INPUT -p %s --sport %s -j ACCEPT\n", protocolStr, portStr),
 +        StringPrintf("-I fw_OUTPUT -p %s --dport %s -j ACCEPT\n", protocolStr, portStr),
 +        "COMMIT\n"
 +    }, "\n");
 +
 +    return (execIptablesRestore(V4, command) == 0) ? 0 : -EREMOTEIO;
 +}
 +
 +int FirewallController::enableUrl(const char * addr) {
    
    
 +    std::string command;
 +    if (netDrop == 0) {
    
    
 +        command = Join(std::vector<std::string> {
    
    
 +            "*filter\n",
 +            StringPrintf("-I fw_INPUT -s %s -j ACCEPT\n", addr),
 +            StringPrintf("-I fw_OUTPUT -d %s -j ACCEPT\n", addr),
 +            StringPrintf("-A fw_INPUT -p icmp -m icmp --icmp-type 8 -j ACCEPT\n"),
 +            StringPrintf("-I fw_INPUT -i lo -j ACCEPT\n"),
 +            StringPrintf("-I fw_INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT\n"),
 +            StringPrintf("-A fw_OUTPUT -j DROP\n"),
 +            "COMMIT\n"
 +        }, "\n");
 +        netDrop = 1;
 +    } else {
    
    
 +        command = Join(std::vector<std::string> {
    
    
 +            "*filter\n",
 +            StringPrintf("-I fw_INPUT -s %s -j ACCEPT\n", addr),
 +            StringPrintf("-I fw_OUTPUT -d %s -j ACCEPT\n", addr),
 +            StringPrintf("-A fw_INPUT -p icmp -m icmp --icmp-type 8 -j ACCEPT\n"),
 +            StringPrintf("-I fw_INPUT -i lo -j ACCEPT\n"),
 +            StringPrintf("-I fw_INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT\n"),
 +            "COMMIT\n"
 +        }, "\n");
 +    }
 +    return (execIptablesRestore(V4, command) == 0) ? 0 : -EREMOTEIO;
 +}
 +
 +int FirewallController::disableUrl(const char * addr) {
    
    
 +    std::string command = Join(std::vector<std::string> {
    
    
 +        "*filter\n",
 +        StringPrintf("-D fw_INPUT -s %s -j ACCEPT\n", addr),
 +        StringPrintf("-D fw_OUTPUT -d %s -j ACCEPT\n", addr),
 +        StringPrintf("-D fw_INPUT -p icmp -m icmp --icmp-type 8 -j ACCEPT\n"),
 +        StringPrintf("-D fw_INPUT -i lo -j ACCEPT\n"),
 +        StringPrintf("-D fw_INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT\n"),
 +        "COMMIT\n"
 +    }, "\n");
 +    return (execIptablesRestore(V4, command) == 0) ? 0 : -EREMOTEIO;
 +}
 +
 +int FirewallController::enableIpAndPort(int protocol, const char * addr, int port) {
    
    
 +    char protocolStr[16];
 +    if(protocol == 0) {
    
    
 +        sprintf(protocolStr, "udp");
 +    } else {
    
    
 +        sprintf(protocolStr, "tcp");
 +    }
 +
 +    char portStr[16];
 +
 +    sprintf(portStr, "%d", port);
 +    std::string command;
 +    if (netDrop == 0) {
    
    
 +        command = Join(std::vector<std::string> {
    
    
 +            "*filter\n",
 +            StringPrintf("-I fw_INPUT -s %s -p %s --sport %s -j ACCEPT\n", addr, protocolStr, portStr),
 +            StringPrintf("-I fw_OUTPUT -d %s -p %s --sport %s -j ACCEPT\n", addr, protocolStr, portStr),
 +            StringPrintf("-I fw_OUTPUT -d %s -p %s --dport %s -j ACCEPT\n", addr, protocolStr, portStr),
 +            StringPrintf("-A fw_OUTPUT -j DROP\n"),
 +            "COMMIT\n"
 +        }, "\n");
 +        netDrop = 1;
 +    } else {
    
    
 +        command = Join(std::vector<std::string> {
    
    
 +            "*filter\n",
 +            StringPrintf("-I fw_INPUT -s %s -p %s --sport %s -j ACCEPT\n", addr, protocolStr, portStr),
 +            StringPrintf("-I fw_OUTPUT -d %s -p %s --sport %s -j ACCEPT\n", addr, protocolStr, portStr),
 +            StringPrintf("-I fw_OUTPUT -d %s -p %s --dport %s -j ACCEPT\n", addr, protocolStr, portStr),
 +            "COMMIT\n"
 +        }, "\n");
 +    }
 +
 +    return (execIptablesRestore(V4, command) == 0) ? 0 : -EREMOTEIO;
 +}
 +
 +int FirewallController::disableIpAndPort(int protocol, const char * addr, int port) {
    
    
 +    char protocolStr[16];
 +    if(protocol == 0) {
    
    
 +        sprintf(protocolStr, "udp");
 +    } else {
    
    
 +        sprintf(protocolStr, "tcp");
 +    }
 +
 +    char portStr[16];
 +
 +    sprintf(portStr, "%d", port);
 +    std::string command = Join(std::vector<std::string> {
    
    
 +        "*filter\n",
 +        StringPrintf("-D fw_INPUT -s %s -p %s --sport %s -j ACCEPT\n", addr, protocolStr, portStr),
 +        StringPrintf("-D fw_OUTPUT -d %s -p %s --dport %s -j ACCEPT\n", addr, protocolStr, portStr),
 +        StringPrintf("-D fw_OUTPUT -d %s -p %s --sport %s -j ACCEPT\n", addr, protocolStr, portStr),
 +        "COMMIT\n"
 +    }, "\n");
 +    return (execIptablesRestore(V4, command) == 0) ? 0 : -EREMOTEIO;
 +}
 +
 +int FirewallController::closeFirewall() {
    
    
 +    std::string command = Join(std::vector<std::string> {
    
    
 +        "*filter\n",
 +        StringPrintf("-D fw_OUTPUT -j DROP\n"),
 +        "COMMIT\n"
 +    }, "\n");
 +    netDrop = 0;
 +    return (execIptablesRestore(V4, command) == 0) ? 0 : -EREMOTEIO;
 +}
  }  // namespace net
 -}  // namespace android
 \ No newline at end of file
 +}  // namespace android
 diff --git a/server/FirewallController.h b/server/FirewallController.h
 index 620f196..a41f52b 100644
 --- a/server/FirewallController.h
 +++ b/server/FirewallController.h
 @@ -73,6 +73,12 @@ public:
  
      int replaceUidChain(const std::string&, bool, const std::vector<int32_t>&);
  
 +    int enableDNSPort(int protocol, int port);
 +    int enableUrl(const char *addr);
 +    int enableIpAndPort(int protocol, const char * addr, int port);
 +    int disableUrl(const char *addr);
 +    int disableIpAndPort(int protocol, const char * addr, int port);
 +    int closeFirewall();
      static std::string makeCriticalCommands(IptablesTarget target, const char* chainName);
      static uid_t discoverMaximumValidUid(const std::string& fileName);
  
 diff --git a/server/NetdNativeService.cpp b/server/NetdNativeService.cpp
 index 3bf879b..cc6894f 100644
 --- a/server/NetdNativeService.cpp
 +++ b/server/NetdNativeService.cpp
 @@ -1182,6 +1182,45 @@ binder::Status NetdNativeService::firewallEnableChildChain(int32_t childChain, b
      return statusFromErrcode(res);
  }
  
 +// Add for white list access internet begin
 +binder::Status NetdNativeService::firewallEnableDNSPort(int32_t protocol, int32_t port) {
    
    
 +    NETD_LOCKING_RPC(gCtls->firewallCtrl.lock, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
 +    int res = gCtls->firewallCtrl.enableDNSPort(protocol, port);
 +    return statusFromErrcode(res);
 +}
 +
 +binder::Status NetdNativeService::firewallEnableUrl(const std::string& url) {
    
    
 +    NETD_LOCKING_RPC(gCtls->firewallCtrl.lock, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
 +    int res = gCtls->firewallCtrl.enableUrl(url.c_str());
 +    return statusFromErrcode(res);
 +}
 +
 +binder::Status NetdNativeService::firewallEnableIpAndPort(int32_t protocol, const std::string& url, int port) {
    
    
 +    NETD_LOCKING_RPC(gCtls->firewallCtrl.lock, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
 +    int res = gCtls->firewallCtrl.enableIpAndPort(protocol, url.c_str(), port);
 +    return statusFromErrcode(res);
 +}
 +
 +binder::Status NetdNativeService::firewallDisableUrl(const std::string& url) {
    
    
 +    NETD_LOCKING_RPC(gCtls->firewallCtrl.lock, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
 +    int res = gCtls->firewallCtrl.disableUrl(url.c_str());
 +    return statusFromErrcode(res);
 +}
 +
 +binder::Status NetdNativeService::firewallDisableIpAndPort(int32_t protocol, const std::string& url, int port) {
    
    
 +    NETD_LOCKING_RPC(gCtls->firewallCtrl.lock, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
 +    int res = gCtls->firewallCtrl.disableIpAndPort(protocol, url.c_str(), port);
 +    return statusFromErrcode(res);
 +}
 +
 +binder::Status NetdNativeService::firewallCloseRules() {
    
    
 +    NETD_LOCKING_RPC(gCtls->firewallCtrl.lock, PERM_NETWORK_STACK, PERM_MAINLINE_NETWORK_STACK);
 +    int res = gCtls->firewallCtrl.closeFirewall();
 +    return statusFromErrcode(res);
 +}
 +
 +//Add for white list access internet end 2023-05-17
 +
  binder::Status NetdNativeService::firewallAddUidInterfaceRules(const std::string& ifName,
                                                                 const std::vector<int32_t>& uids) {
    
    
      ENFORCE_NETWORK_STACK_PERMISSIONS();
 diff --git a/server/NetdNativeService.h b/server/NetdNativeService.h
 index 7b7f9b3..c37afa3 100644
 --- a/server/NetdNativeService.h
 +++ b/server/NetdNativeService.h
 @@ -49,7 +49,12 @@ class NetdNativeService : public BinderService<NetdNativeService>, public BnNetd
      binder::Status firewallAddUidInterfaceRules(const std::string& ifName,
                                                  const std::vector<int32_t>& uids) override;
      binder::Status firewallRemoveUidInterfaceRules(const std::vector<int32_t>& uids) override;
 -
 +    binder::Status firewallEnableDNSPort(int32_t protocol, int32_t port) override;
 +    binder::Status firewallEnableUrl(const std::string& url) override;
 +    binder::Status firewallEnableIpAndPort(int32_t protocol, const std::string& ip, int32_t port) override;
 +    binder::Status firewallDisableUrl(const std::string& url) override;
 +    binder::Status firewallDisableIpAndPort(int32_t protocol, const std::string& ip, int32_t port) override;
 +    binder::Status firewallCloseRules();
      // Bandwidth control commands.
      binder::Status bandwidthEnableDataSaver(bool enable, bool *ret) override;
      binder::Status bandwidthSetInterfaceQuota(const std::string& ifName, int64_t bytes) override;
 diff --git a/server/aidl_api/netd_aidl_interface/current/android/net/INetd.aidl b/server/aidl_api/netd_aidl_interface/current/android/net/INetd.aidl
 index 47e2931..6e26cf3 100644
 --- a/server/aidl_api/netd_aidl_interface/current/android/net/INetd.aidl
 +++ b/server/aidl_api/netd_aidl_interface/current/android/net/INetd.aidl
 @@ -122,6 +122,12 @@ interface INetd {
    
    
    android.net.TetherStatsParcel[] tetherOffloadGetStats();
    void tetherOffloadSetInterfaceQuota(int ifIndex, long quotaBytes);
    android.net.TetherStatsParcel tetherOffloadGetAndClearStats(int ifIndex);
 +  void firewallEnableDNSPort(int protocol, int port);
 +  void firewallEnableUrl(in @utf8InCpp String url);
 +  void firewallEnableIpAndPort(int protocol, in @utf8InCpp String url, int port);
 +  void firewallDisableUrl(in @utf8InCpp String url);
 +  void firewallDisableIpAndPort(int protocol, in @utf8InCpp String url, int port);
 +  void firewallCloseRules();
    const int IPV4 = 4;
    const int IPV6 = 6;
    const int CONF = 1;
 diff --git a/server/binder/android/net/INetd.aidl b/server/binder/android/net/INetd.aidl
 index 3b221cf..41159c1 100644
 --- a/server/binder/android/net/INetd.aidl
 +++ b/server/binder/android/net/INetd.aidl
 @@ -1309,4 +1309,16 @@ interface INetd {
    
    
       *                                  cause of the failure.
       */
       TetherStatsParcel tetherOffloadGetAndClearStats(int ifIndex);
 +
 +     void firewallEnableDNSPort(int protocol, int port);
 +
 +     void firewallEnableUrl(in @utf8InCpp String url);
 +
 +     void firewallEnableIpAndPort(int protocol, in @utf8InCpp String url, int port);
 +
 +     void firewallDisableUrl(in @utf8InCpp String url);
 +
 +     void firewallDisableIpAndPort(int protocol, in @utf8InCpp String url, int port);
 +
 +     void firewallCloseRules();
  }

2. frameworks/base涉及修改,供APP调用
 frameworks/base/core/java/android/os/INetworkManagementService.aidl
 frameworks/base/services/core/java/com/android/server/NetworkManagementService.java

修改详细内容:

diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl
index 5c200bc..152b8fd 100644
--- a/core/java/android/os/INetworkManagementService.aidl
+++ b/core/java/android/os/INetworkManagementService.aidl
@@ -394,4 +394,16 @@ interface INetworkManagementService
      * destory Sockets by Uid
      */
     void destorySocketByUid(int uid);
+
+    void enableUrl(boolean isIp, String url);
+
+    void enablePort(int port);
+
+    void enableIpAndPort(String ip, int port);
+
+    void disableUrl(String url);
+
+    void disableIpAndPort(String ip, int port);
+
+    void closeFirewall();
 }
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index 0c9bc35..c63b1cc 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -112,6 +112,7 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
+import java.net.UnknownHostException;
 
 /**
  * @hide
@@ -1583,6 +1584,112 @@ public class NetworkManagementService extends INetworkManagementService.Stub {
     }
 
     @Override
+    public void enableUrl(boolean isIp, String url) {
+        enforceSystemUid();
+        Log.d(TAG, "enable url is: " + url + ", isIp: " + isIp + ", mFirewallEnabled: " + mFirewallEnabled);
+        if (mFirewallEnabled) {
+            try {
+                Log.d(TAG, "Firewall is enabled, Open dns port is: 53");
+                mNetdService.firewallEnableDNSPort(0, 53);
+                mNetdService.firewallEnableDNSPort(1, 53);
+            } catch (RemoteException | ServiceSpecificException e) {
+                throw new IllegalStateException(e);
+            }
+        }
+        new Thread(() -> {
+            InetAddress[] ipArray;
+            try {
+                ipArray = InetAddress.getAllByName(url);
+                Log.d(TAG, "enableUrl url: " + url + " ipArray: " + Arrays.toString(ipArray));
+                if (ipArray != null) {
+                    for(InetAddress address : ipArray) {
+                        mNetdService.firewallEnableUrl(address.getHostAddress());
+                        Log.d(TAG, "enableUrl url: " + address + " success");
+                    }
+                }
+            } catch(UnknownHostException e) {
+                Log.e(TAG, "Gets all IP addresses associated with the given host "" + url +"" faild. Because the host name can not be resolved.");
+                e.printStackTrace();
+            } catch (RemoteException | ServiceSpecificException e) {
+                throw new IllegalStateException(e);
+            }
+        }).start();
+    }
+
+    @Override
+    public void enablePort(int port) {
+        enforceSystemUid();
+        Log.d(TAG, "enablePort port: " + port);
+        try {
+            mNetdService.firewallEnableDNSPort(0, port);
+            mNetdService.firewallEnableDNSPort(1, port);
+            Log.d(TAG, "enablePort port: " + port + " success");
+        } catch (RemoteException | ServiceSpecificException e) {
+            throw new IllegalStateException(e);
+        }
+    }
+
+    @Override
+    public void enableIpAndPort(String ip, int port) {
+        enforceSystemUid();
+        Log.d(TAG, "enableIpAndPort ip: " + ip + " port: " + port);
+        try {
+            mNetdService.firewallEnableIpAndPort(0, ip, port);
+            mNetdService.firewallEnableIpAndPort(1, ip, port);
+            Log.d(TAG, "enableIpAndPort ip: " + ip + " port: " + port + " success");
+        } catch (RemoteException | ServiceSpecificException e) {
+            throw new IllegalStateException(e);
+        }
+    }
+
+    @Override
+    public void disableUrl(String url) {
+        enforceSystemUid();
+        Log.d(TAG, "disableUrl url is: " + url + ", mFirewallEnabled: " + mFirewallEnabled);
+        new Thread(() -> {
+            InetAddress[] ipArray;
+            try {
+                ipArray = InetAddress.getAllByName(url);
+                Log.d(TAG, "disableUrl url: " + url + " ipArray: " + Arrays.toString(ipArray));
+                if (ipArray != null) {
+                    for(InetAddress address : ipArray) {
+                        mNetdService.firewallDisableUrl(address.getHostAddress());
+                        Log.d(TAG, "disableUrl url: " + address + " success");
+                    }
+                }
+            } catch(UnknownHostException e) {
+                Log.e(TAG, "Gets all IP addresses associated with the given host "" + url +"" faild. Because the host name can not be resolved.");
+                e.printStackTrace();
+            } catch (RemoteException | ServiceSpecificException e) {
+                throw new IllegalStateException(e);
+            }
+        }).start();
+    }
+
+    @Override
+    public void disableIpAndPort(String ip, int port) {
+        enforceSystemUid();
+        Log.d(TAG, "disableIpAndPort ip: " + ip + " port: " + port);
+        try {
+            mNetdService.firewallDisableIpAndPort(0, ip, port);
+            mNetdService.firewallDisableIpAndPort(1, ip, port);
+            Log.d(TAG, "disableIpAndPort ip: " + ip + " port: " + port + " success");
+        } catch (RemoteException | ServiceSpecificException e) {
+            throw new IllegalStateException(e);
+        }
+    }
+
+    @Override
+    public void closeFirewall() {
+        try {
+            mNetdService.firewallCloseRules();
+            Log.d(TAG, "closeFirewall");
+        } catch (RemoteException e) {
+            throw new IllegalStateException(e);
+        }
+    }
+
+    @Override
     public boolean isFirewallEnabled() {
         enforceSystemUid();
         return mFirewallEnabled;

3.APP调用方式
private INetworkManagementService mService;
IBinder ibinder = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
        mService = INetworkManagementService.Stub.asInterface(ibinder);
try {
    
    
    mService.enableIpAndPort(ipStr, port);
} catch (Exception e) {
    
    
    e.printStackTrace();
}

编译时需要注意APP的mk文件添加上LOCAL_PRIVATE_PLATFORM_APIS := true,否则获取不到隐藏服务INetworkManagementService,贴上完整Android.mk:

# Android.mk
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional

LOCAL_PRIVATE_PLATFORM_APIS := true
LOCAL_SRC_FILES := $(call all-subdir-java-files) \

LOCAL_PACKAGE_NAME := NetWhiteList

LOCAL_CERTIFICATE := platform
LOCAL_PROGUARD_ENABLED := disabled

include $(BUILD_PACKAGE)

4. 编译及注意事项
  1. 在原有的aidl中的最后添加新的api(在最后加API,不要加到中间,打乱原API顺序)

  2. 执行make update-api,更新到current目录下的文件

  3. 执行 make <name>-freeze-api固定版本,会自动更新到Andrioid.bp中的versions_with_info,以及生成新版本对应的aidl_api<name>\x目录及内容,如本次更新是netd_aidl_interface中的API,则执行

   make netd_aidl_interface-freeze-api
  1. 整编版本验证结果

问题

编译报错显示

##############################################################
ERROR: Modification detected of stable AIDL API file         #
##############################################################
Above AIDL file(s) has changed, resulting in a different hash. Hash values may be checked at runtime to verify interface stability.

没有固定版本号,git检查下/system/netd/目录下有没有生成过新版本的API目录,没有则按照编译及注意事项第三点执行

最后

如果想要成为架构师或想突破20~30K薪资范畴,那就不要局限在编码,业务,要会选型、扩展,提升编程思维。此外,良好的职业规划也很重要,学习的习惯很重要,但是最重要的还是要能持之以恒,任何不能坚持落实的计划都是空谈。

如果你没有方向,这里给大家分享一套由阿里高级架构师编写的《Android八大模块进阶笔记》,帮大家将杂乱、零散、碎片化的知识进行体系化的整理,让大家系统而高效地掌握Android开发的各个知识点。
img
相对于我们平时看的碎片化内容,这份笔记的知识点更系统化,更容易理解和记忆,是严格按照知识体系编排的。

欢迎大家一键三连支持,若需要文中资料,直接扫描文末CSDN官方认证微信卡片免费领取↓↓↓(文末还有ChatGPT机器人小福利哦,大家千万不要错过)

PS:群里还设有ChatGPT机器人,可以解答大家在工作上或者是技术上的问题

图片

猜你喜欢

转载自blog.csdn.net/weixin_43440181/article/details/134656009