VpnService在几秒钟后无故停止

时间:2019-06-27 11:14:57

标签: java android network-programming vpn android-vpn-service

我编写了以下代码,我想建立一个VPN连接以获取数据包(已安装的应用程序的本地流量),然后在它们与我的规则(源和目标IP等)匹配时放开它们。所以我已经为这个应用程序(VPN连接)编写了代码,但是当我运行它时,通知栏中会出现一个钥匙图标,并且在将近10秒钟后,钥匙图标会无故消失(VPN断开连接)。此外,在VPN连接期间不会传输任何数据(最好说PACKET)(我的意思是类似WhatsApp的设备应用无法访问互联网)

设备android版本:8
设备(电话)WIFI适配器IP为:192.168.1.101
本地路由(调制解调器)网关地址:192.168.1.1

我的代码:

public class MyVpnService extends VpnService {

private Thread mThread;
private ParcelFileDescriptor mInterface;
private static final int MAX_PACKET_SIZE = 32767;
//a. Configure a builder for the interface.
Builder builder = new Builder();

// Services interface
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    // Start a new session by creating a new thread.
    mThread = new Thread(new Runnable() {
        @Override
        public void run() {
            try {
                //a. Configure the TUN and get the interface.
                mInterface = builder.setSession("MyVPNService")
                        .addAddress("192.168.1.0", 24)
                        .addDnsServer("8.8.8.8")
                        .addRoute("0.0.0.0", 0).establish();
                //b. Packets to be sent are queued in this input stream.
                FileInputStream in = new FileInputStream(
                        mInterface.getFileDescriptor());
                //b. Packets received need to be written to this output stream.
                FileOutputStream out = new FileOutputStream(
                        mInterface.getFileDescriptor());
                //c. The UDP channel can be used to pass/get ip package to/from server
                DatagramChannel tunnel = DatagramChannel.open();
                tunnel.configureBlocking(false);
                // Connect to the server, localhost is used for demonstration only.
                tunnel.connect(new InetSocketAddress("127.0.0.1", 8087));
                //d. Protect this socket, so package send by it will not be feedback to the vpn service.
                protect(tunnel.socket());
                ByteBuffer packet = ByteBuffer.allocate(MAX_PACKET_SIZE);

                //e. Use a loop to pass packets.
                int length=0;
                while (true) {
                    Log.d("VPNservice", "5");
                    length= in.read(packet.array());
                    if (length > 0) {
                        packet.limit(length);
                        tunnel.write(packet);
                        // There might be more outgoing packets.
                        Log.d("VPNservice", "6");
                    }
                    Log.d("VPNservice", "7");
                    length = tunnel.read(packet);
                    Log.d("VPNservice", "8");
                    if (length > 0) {
                        if (packet.get(0) != 0) {
                            out.write(packet.array(), 0, length);
                            Log.d("VPNservice", "9");
                        }
                        packet.clear();
                        Log.d("VPNservice", "10");
                    }
                    Thread.sleep(100);
                    Log.d("VPNservice", "11");
                }

            } catch (Exception e) {
                Log.d("VPNservice", "20");
                e.printStackTrace();
            } finally {
                try {
                    if (mInterface != null) {
                        mInterface.close();
                        mInterface = null;
                    }
                } catch (Exception e) {

                }
            }
        }

    }, "MyVpnRunnable");

    //start the service
    mThread.start();
    return START_STICKY;
}

@Override
public void onDestroy() {
    // TODO Auto-generated method stub
    if (mThread != null) {
        mThread.interrupt();
    }
    super.onDestroy();
}
}

logcat结果:

2019-06-27 15:24:32.697 21338-21640/? D/VPNservice: 5
2019-06-27 15:24:32.698 21338-21640/? D/VPNservice: 7
2019-06-27 15:24:32.698 21338-21640/? D/VPNservice: 8
2019-06-27 15:24:34.699 21338-21640/? D/VPNservice: 11
2019-06-27 15:24:34.699 21338-21640/? D/VPNservice: 5
2019-06-27 15:24:34.700 21338-21640/? D/VPNservice: 6
2019-06-27 15:24:34.700 21338-21640/? D/VPNservice: 7
2019-06-27 15:24:34.700 21338-21640/? D/VPNservice: 8
2019-06-27 15:24:36.700 21338-21640/? D/VPNservice: 11
2019-06-27 15:24:36.700 21338-21640/? D/VPNservice: 5
2019-06-27 15:24:36.701 21338-21640/? D/VPNservice: 20
2019-06-27 15:25:43.121 21863-21885/? D/VPNservice: 5
2019-06-27 15:25:43.121 21863-21885/? D/VPNservice: 7
2019-06-27 15:25:43.122 21863-21885/? D/VPNservice: 8
2019-06-27 15:25:45.122 21863-21885/? D/VPNservice: 11
2019-06-27 15:25:45.122 21863-21885/? D/VPNservice: 5
2019-06-27 15:25:45.124 21863-21885/? D/VPNservice: 6
2019-06-27 15:25:45.124 21863-21885/? D/VPNservice: 7
2019-06-27 15:25:45.124 21863-21885/? D/VPNservice: 8
2019-06-27 15:25:47.124 21863-21885/? D/VPNservice: 11
2019-06-27 15:25:47.124 21863-21885/? D/VPNservice: 5
2019-06-27 15:25:47.125 21863-21885/? D/VPNservice: 6
2019-06-27 15:25:47.125 21863-21885/? D/VPNservice: 7
2019-06-27 15:25:47.125 21863-21885/? D/VPNservice: 8
2019-06-27 15:25:49.125 21863-21885/? D/VPNservice: 11
2019-06-27 15:25:49.126 21863-21885/? D/VPNservice: 5
2019-06-27 15:25:49.127 21863-21885/? D/VPNservice: 20

MainActivity.java:

package com.example.vpn_test;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.net.VpnService;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Button btn= findViewById(R.id.btn);
    btn.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view)
        {
            Intent intent = VpnService.prepare(MainActivity.this);
            if (intent != null) {
                startActivityForResult(intent, 0);
            } else {
                onActivityResult(0, RESULT_OK, null);
            }
        }
    });

}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (resultCode == RESULT_OK) {
        Intent intent = new Intent(this, MyVpnService.class);
        startService(intent);
    }
}
}

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.vpn_test">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />

<application

    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    <activity android:name=".MainActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <service
        android:name="com.example.vpn_test.MyVpnService"
        android:permission="android.permission.BIND_VPN_SERVICE" >
        <intent-filter>
            <action android:name="android.net.VpnService" />
        </intent-filter>
    </service>
</application>

0 个答案:

没有答案