Androidは、Iptablesを利用してネットワーク白黒リスト(ファイアウォール)を実現する。


一、概要
この簡単なペンを読んでいる人がIptablesを簡単に理解するために、ここで強引に百度の概念を作りました。Iptablesの各種の配置規則とカーネルの管理運行メカニズムを深く理解したいならば、自行してください。これらは本簡筆の目的ではありません。
余談はさておいて、本文を始めます。
-->以下の概要はbaiduから来ています。読者は適宜スキップできます。
iptablesの前身はipfirewall(カーネル1.x時代)といい、freeBSDから移植されたもので、カーネルの中で働くことができ、パケットを検査する簡易アクセス制御ツールです。しかし、ipfirewallの機能は極めて限られています。(すべての規則をカーネルに入れる必要があります。このように規則が実行できます。カーネルに入れるのは一般的に難しいです。)カーネルが2.xシリーズに発展すると、ソフトウェアはipchainsと名前を変えて、複数のルールを定義して、彼らをつなぎ合わせて役割を果たしますが、今はiptablesといいます。ルールをリストに構成して、絶対的に詳細なアクセス制御機能を実現します。
彼らはすべてユーザーの空間の中で働くので、規則のツールを定義して、自身はファイアウォールとは言えません。彼らが定義したルールは、カーネル空間の中のnetfilterに読み込ませ、ファイアウォールを作動させることができます。カーネルを入れるところは特定の位置なら、tcp/ipのプロトコルスタックが通るところでなければなりません。このtcp/ipプロトコルスタックを通過しなければならないところで、読み取りルールが実現できるところをnetfilterといいます。
-->以下は本稿の注目点である。
二、Iptablesネットワークモノクロリスト(ファイアウォール)実現の詳細
いくつかの権限の問題を考慮して、このような方法を実行するためにsystemserverを作成します。そして、3つのアプリケーションにmanagerを提供し、これにより、呼び出し時にいくつかの権限の制限を排除することができる。また、本論文では簡単な参考概要を作成するだけですので、白黒リストを追加する方法とiptablesルールだけを提供しています。削除ルールなどは提供されていません。
2.1、システムズセーバーを作成する
2.1.1、system/sepolicy/service.teに追加

type fxjnet_service, system_api_service, system_server_service, service_manager_type;
2.2.2、在/system/sepolicy/service_contextsに下記のように追加します。

fxjnet      u:object_r:fxjnet_service:s0
2.2.3、フレームワーク/base/core/java/android/content/Conttext.javaに追加
これを追加しなくてもいいですが、後からの呼び出しが便利なように追加しました。このステップをスキップすると、後ろにContect.FXJNET_が現れます。SERVICEのところは全部文字列で代用すればいいです。

public static final String FXJNET_SERVICE="fxjnet";
2.2.4、フレームワーク/base/core/java/android/ap/System ServiceRegistry.javaの静的コードブロックに以下のコードを追加してserviceを登録します。

registerService(Context.FXJNET_SERVICE, FXJNETManager.class,
       new CachedServiceFetcher<FXJNETManager>() {
       @Override
       public FXJNETManager createService(ContextImpl ctx) {
       IBinder b = ServiceManager.getService(Context.FXJNET_SERVICE);
       IFXJNETService service = IFXJNETService.Stub.asInterface(b);
       return new FXJNETManager(ctx, service);
 }});
2.2.5、フレームワーク/base/services/java/com/android/server/SystemServer.javaに下記のコードを追加し、serviceをsystemServerに加入する。

ServiceManager.addService(Context.FXJNET_SERVICE, new FXJNETService());
2.2.6、AIDLファイル

package android.os;
interface IFXJNETService{
  void addNetworkRestriction(List<String> ipName,int type);
}
2.2.7、外部に提供するFXJNETManger

package android.app;
import android.os.IFXJNETService;
import android.os.RemoteException;
import android.content.Context;
public class FXJNETManager{

 IFXJNETService mService;
 public FXJNETManager(Context ctx,IFXJNETService service){
    mService=service;
 }
 public void addNetworkRestriction(List<String> ipName,int type) {
    try{
      mService.addNetworkRestriction(ipName,type);
   }catch (RemoteException e){
   }
 }//end addNetworkRestriction
}

2.2.8、システムサービスすなわちAIDLのServerを実現する

package com.android.server;

import android.os.IFXJNETService;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

public class FXJNETService extends IFXJNETService.Stub {
final File file = new File("/data/fxj/", "firewall.sh");
  /**
   *   {  IP  }      
   */
  public void addNetworkRestriction(List<String> ipName,int type) {
      String str= getIPlist(type,ipName);
      setiptablesRestriction();
  }
//  Iptables   ,1-    ;2-   
 private String getIPlist(int type,List<String> iplist){
    StringBuilder sb = new StringBuilder();
    sb.append("echo runscript start
"); sb.append("iptables -F OUTPUT
"); if (type == 1){ if (iplist != null && iplist.size() > 0){ for (int i = 0 ; i < iplist.size() ;i++){ String ipname = iplist.get(i); sb.append("echo blacklist mode
"); sb.append("iptables -I OUTPUT -d "); sb.append(ipname); sb.append(" -j DROP
"); } } }else if (type == 2){ if (iplist != null && iplist.size() > 0){ for (int i = 0 ; i < iplist.size() ; i++){ String ipname =iplist.get(i); sb.append("echo whitelist mode
"); sb.append("iptabless -P OUTPUT DROP
"); sb.append("iptables -I OUTPUT -d "); sb.append(ipname); sb.append(" -j ACCEPT
"); } } } sb.append("run script end
"); return sb.toString(); } private void setiptablesRestriction(String ipName){ final FXJScriptRunner runner = new FXJScriptRunner(file,ipName,new StringBuilder()); new Thread(new Runnable() { @Override public void run() { runner.run(); } }).start(); } }
2.2.9、IPTABLESスクリプトコマンドを実行するツール類

package com.android.server;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;

import android.os.FileUtils;
import android.os.SystemProperties;
import android.util.Log;

public class FXJScriptRunner extends Thread{
  private final File file;
  private final String script;
  private final StringBuilder res;
  public int exitcode = -1;
  private final String TAG = "ScriptRunner" ;
  
  public ScriptRunner(File file, String script, StringBuilder res,
      boolean asroot) {
    this.file = file;
    this.script = script;
    this.res = res;
  }

  @Override
  public void run() {
    // TODO Auto-generated method stub
    try {
      file.delete();
      file.createNewFile();
      final String abspath = file.getAbsolutePath();
      // make sure we have execution permission on the script file
      FileUtils.setPermissions(abspath, 00700, -1, -1);
      Runtime.getRuntime().exec("chmod 777 " + abspath).waitFor();//    sh      
      // Write the script to be executed
      final OutputStreamWriter out = new OutputStreamWriter(
          new FileOutputStream(file));
      if (new File("/system/bin/sh").exists()) {
        out.write("#!/system/bin/sh
"); } out.write(script); if (!script.endsWith("
")) out.write("
"); out.write("exit 0
"); out.flush(); out.close(); // SystemProperties.set("ctl.start", "fxjmotnitor") service, , //fxjmotnitor service , SystemProperties.set("ctl.start", "fxjmotnitor"); } catch (Exception ex) { if (res != null) res.append("
" + ex); } finally { //destroy(); } } }
三、fxjmotnitor serviceの作成手順は以下の通りです。
3.1、Serviceが起動時に動作するように、system/core/rootdir/init.rcに次のように追加します。

service fxjmotnitor /system/bin/sh /data/fxj/firewall.sh
 class main
 oneshot
 seclabel u:r:fxjmotnitor:s0
3.2、sepolicy/ディレクトリの下でfxjmotnitor.teファイルを作成します。内容は以下の通りです。

type fxjmotnitor, domain;
type fxjmotnitor_exec, exec_type, file_type;
init_daemon_domain(fxjmotnitor)
allow fxjmotnitor shell_exec:file { entrypoint getattr read };
3.3、はい/sepolicy/file_contextsに追加

/data/fxj/firewall.sh  u:object_r:fxjmotnitor_exec:s0
3.4、sepolicy/Android.mkの

BOARD_SEPOLICY_UNION += \
#    
......\
fxjmotnitor.te \
......\
以上はiptables規則に基づいてipアドレスを制御し、携帯電話のipがアクセスできないプロセスの詳細を制限しています。もちろんiptablesの役割はこれに限らず、興味のあるものは自分で学習を知ることができます。私たちを応援してください。