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

其中一个代码片段:

typescript 复制代码
 // 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接口中,在跟一根找到它的实现

scss 复制代码
 // /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);
 }
c 复制代码
 // /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涉及修改文件

bash 复制代码
 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/

修改详细内容:

less 复制代码
 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调用

bash 复制代码
 frameworks/base/core/java/android/os/INetworkManagementService.aidl
 frameworks/base/services/core/java/com/android/server/NetworkManagementService.java

修改详细内容:

diff 复制代码
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调用方式

ini 复制代码
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:

makefile 复制代码
# 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,则执行

    go 复制代码
    make netd_aidl_interface-freeze-api
  4. 整编版本验证结果

问题

编译报错显示

bash 复制代码
```
##############################################################
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目录,没有则按照编译及注意事项第三点执行

相关推荐
有位神秘人24 分钟前
Android中Notification的使用详解
android·java·javascript
·云扬·33 分钟前
MySQL Binlog落盘机制深度解析:性能与安全性的平衡艺术
android·mysql·adb
独自破碎E2 小时前
【BISHI9】田忌赛马
android·java·开发语言
代码s贝多芬的音符3 小时前
android 两个人脸对比 mlkit
android
darkb1rd5 小时前
五、PHP类型转换与类型安全
android·安全·php
gjxDaniel5 小时前
Kotlin编程语言入门与常见问题
android·开发语言·kotlin
csj505 小时前
安卓基础之《(22)—高级控件(4)碎片Fragment》
android
峥嵘life6 小时前
Android16 【CTS】CtsMediaCodecTestCases等一些列Media测试存在Failed项
android·linux·学习
stevenzqzq7 小时前
Compose 中的状态可变性体系
android·compose
似霰7 小时前
Linux timerfd 的基本使用
android·linux·c++