一種實現android免root防火牆的方法,android免root防火牆

來源:互聯網
上載者:User

一種實現android免root防火牆的方法,android免root防火牆

在使用android手機過程中,發現自己手機的流量經常被一些不小心下載的帶廣告的應用偷走了。自己在各個市場上搜了下,絕大部分防火牆都是需要手機root的。其中多數又是修改自著名的Droidwall,例如github上這個項目:https://github.com/skullone/android_firewall。其原理是在root後的機器使用root許可權來配置iptable,利用linux這個內建的防火牆實行流量控制。

但root本身破壞了android的安全機制,反而容易導致系統被惡意代碼利用。在googleplay上,終於找到一款noroot firewall。它利用了android的vpnservice技術,實現了免root的防火牆。高度興趣,於是在網上找了些資料,又自己實現了一個免root防火牆(各主要android市場搜“免root防火牆”,藍色盾牌表徵圖),這裡分享下自己的經驗。

Android系統支援配置VPN service。可以在設定->更多->VPN中添加。但系統只支援部分VPN協議。如果使用者想實現自己的VPN協議,那怎麼辦呢?為了支援這種擴充,Android提供了VpnService類。這是一個Service的子類。一旦start了該service,它會建立一個類似於應用代理的服務。任何應用外出的包,都會先發給該服務,然後該服務再轉寄到網路上。於是這個VpnService就成為需要使用網路的應用和網路伺服器之間的一個中間人。這就提供了一個機會來控制外出流量。

VpnService和client互動

那VpnService是如何跟client應用通訊的呢?這裡利用了linux的TUN/TAP機制。TUN/TAP提供了一種虛擬軟網路介面(相對於物理網卡而言)。開發人員可以開啟這個軟介面裝置,擷取一個檔案描述符(裝置即檔案),然後read就是從其中讀資料,write就是向其中寫資料。不同於物理網卡介面是把資料發送到網上或者接收自網上(其實是寫/讀到核心裡,然後網卡驅動發/收到網上),該虛擬網路介面是讀/寫到應用空間。當建立其TUN/TAP後,client應用本來要發送到實際網卡的包,都會發送給這個虛擬tun/tap,此時vpnservice就可以read到client發送的資料;vpnservice可以寫資料到tun/tap中,此時client如果recv或read,那就會讀取這個虛擬網口,擷取vpnservice寫的資料。這個我估計是通過修改路由表實現的,使得所有的網樓包都優先走tun/tap虛擬網口。

tun和tap的區別是前者這有IP頭和IP負載(即三層和以上),而tap包括資料連結層頭(二層和以上)。在Android中,實際是一個tun,讀寫的資料是IP原始報文。為了驗證vpnservice建立了一個虛擬網口,可以下載noroot filewall,然後通過adb shell netcfg。如果已經開啟了vpnservice,則名字是tun0的介面,其狀態是UP。

關於tun/tap可以參考http://backreference.org/2010/03/26/tuntap-interface-tutorial/和https://www.kernel.org/doc/Documentation/networking/tuntap.txt。這是linux的機制,而不僅僅是android的。

VpnService和網路伺服器互動

那VpnService如果把收到的資料發送到網上呢?不同於普通linux允許使用者發送原始ip報文,Android安全機制只允許socket發送普通的tcp/udp報文。這就要求我們把通過tun收到的ip報文進行解包,擷取其tcp/udp payload(即應用程式層資料),然後通過send發送到伺服器。在接收的時候,需要把伺服器過來的recv的資料,添加tcp/udp頭和ip頭,然後write到tun中。對於tcp具體而言要複雜很多:

  • 如果受到的是syn包,則要connect
  • 如果connect成功,則需要返回給tun一個syn ack。這樣子三向交握結束(因為不用處理最後一個ack)。
  • 傳輸的時候要記錄雙向的seq,以產生seq和ack序號。
  • 收到fin包的時候需要close,並返回fin ack。有時候是伺服器發起串連終止,此時需要向用戶端發fin。
  • 收到rst同樣要close串連。

某種程度上,這裡要重現實現一個tcp協議棧,不過要比完整的簡單很多。

實現

首先要start service,這一般在activity提供一個button實現。並不是直接startservice,而是要先開啟一個需要使用者同意的activity,當使用者同意時,才能開啟service。這是為了防止惡意vpnservice偷窺網路資料。

參考這段代碼(在activity中):

    public void enableVpnService() {        Intent intent = MyVpnService.prepare(getApplicationContext());        if (intent != null) {            startActivityForResult(intent, 0);        } else {            onActivityResult(0, RESULT_OK, null);        }    }    @Override    protected void onActivityResult(int request, int result, Intent data) {        if (result == RESULT_OK) {            Intent intent = new Intent(this, MyVpnService.class);            startService(intent);        }    }

然後在service的onstartcommand中,需要建立tun。

為了方便VpnService建立tun,Android提供了一個Builder類VpnService.Builder。例如我們可以調用:

Builder builder = new Builder();builder.addAddress("10.0.8.1", 32).addRoute("0.0.0.0", 0).setSession("Firewall")                .setMtu(1500);ParcelFileDescriptor interface = builder.establish();

此interface就代表著tun。只可以對其進行讀寫。為了避免ANR,最好是建立一個thread來做。

對於真實跟外界互動的socket,如果你對其不做任何處理,那資料會再次發送到tun中,造成死迴圈。所以此時要調用VpnService.protect保證該socket發送的資料都直接發到物理網卡。

Android提供了一個ToyVpn的sample project,可以搜尋看其代碼,也可以在eclipse建立android sample code來看。另外可以參考下這篇介紹文章。

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.