【问题标题】:Cannot start VPN using Toyvpn无法使用 Toyvpn 启动 VPN
【发布时间】:2014-07-05 09:46:44
【问题描述】:

我会尽量做到描述性 我是 android 新手,我正在制作一个 android 应用程序 在该应用程序中,我希望能够看到从移动设备发出的 HTTP 请求的地址(在他们前往的网站上)。 所以我环顾四周,我发现要做到这一点,我需要使用 VPN 并且 android 4.0+ 有一个使用 ToyVPNService 实现的谷歌提供的 VPNService 所以我得到了这个服务并开始改变它,所以我可以在不需要使用服务器的情况下使用它 我想按如下方式使用 VPN: 1-捕获HTTP请求 2-阅读他们的目的地 3-将他们送回原路

所以我使用了 VPNService 并开始对其进行修改,这样我就不需要实际的服务器了 这是我正在使用的代码

    package com.example.testingservice;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.net.VpnService;
import android.os.Handler;
import android.os.Message;
import android.os.ParcelFileDescriptor;
import android.util.Log;
import android.widget.Toast;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.nio.ByteBuffer;
import java.nio.channels.DatagramChannel;
import java.util.Enumeration;
public class SO1 extends VpnService implements Handler.Callback, Runnable {
private static final String TAG = "ToyVpnService";

private Handler mHandler;
private Thread mThread;

private ParcelFileDescriptor mInterface;

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    // The handler is only used to show messages.
    if (mHandler == null) {
        mHandler = new Handler(this);
    }

    // Stop the previous session by interrupting the thread.
    if (mThread != null) {
        mThread.interrupt();
    }

    // Start a new session by creating a new thread.
    mThread = new Thread(this, "ToyVpnThread");
    mThread.start();
    return START_STICKY;
}

@Override
public void onDestroy() {
    if (mThread != null) {
        mThread.interrupt();
    }
}

@Override
public boolean handleMessage(Message message) {
    if (message != null) {
        Toast.makeText(this, message.what, Toast.LENGTH_SHORT).show();
    }
    return true;
}

@Override
public synchronized void run() {
    Log.i(TAG,"running vpnService");
    try {
        runVpnConnection();
    } catch (Exception e) {
        e.printStackTrace();
        //Log.e(TAG, "Got " + e.toString());
    } finally {
        try {
            mInterface.close();
        } catch (Exception e) {
            // ignore
        }
        mInterface = null;

        mHandler.sendEmptyMessage(R.string.disconnected);
        Log.i(TAG, "Exiting");
    }
}

private boolean runVpnConnection() throws Exception {

    configure();

    FileInputStream in = new FileInputStream(mInterface.getFileDescriptor());

    // Allocate the buffer for a single packet.
    ByteBuffer packet = ByteBuffer.allocate(32767);

    // We keep forwarding packets till something goes wrong.
    while (true) {
        // Assume that we did not make any progress in this iteration.
        boolean idle = true;

        // Read the outgoing packet from the input stream.
        int length = in.read(packet.array());
        if (length > 0) {

            Log.i(TAG,"************new packet");
            System.exit(-1);
            while (packet.hasRemaining()) {
                Log.i(TAG,""+packet.get());
                //System.out.print((char) packet.get());
            }
            packet.limit(length);
            //  tunnel.write(packet);
            packet.clear();

            // There might be more outgoing packets.
            idle = false;
        }
        Thread.sleep(50);
    }
}

public String getLocalIpAddress()
{
    try {
        for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) {
            NetworkInterface intf = en.nextElement();
            for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements();) {
                InetAddress inetAddress = enumIpAddr.nextElement();
                Log.i(TAG,"****** INET ADDRESS ******");
                Log.i(TAG,"address: "+inetAddress.getHostAddress());
                Log.i(TAG,"hostname: "+inetAddress.getHostName());
                Log.i(TAG,"address.toString(): "+inetAddress.getHostAddress().toString());
                if (!inetAddress.isLoopbackAddress()) {
                    //IPAddresses.setText(inetAddress.getHostAddress().toString());
                    Log.i(TAG,"IS NOT LOOPBACK ADDRESS: "+inetAddress.getHostAddress().toString());
                    return inetAddress.getHostAddress().toString();
                } else{
                    Log.i(TAG,"It is a loopback address");
                }
            }
        }
    } catch (SocketException ex) {
        String LOG_TAG = null;
        Log.e(LOG_TAG, ex.toString());
    }

    return null;
}

private void configure() throws Exception {
    // If the old interface has exactly the same parameters, use it!
    if (mInterface != null) {
        Log.i(TAG, "Using the previous interface");
        return;
    }

    // Configure a builder while parsing the parameters.
    Builder builder = new Builder();
    String SS=getLocalIpAddress();
    builder.setMtu(1500);
  //  builder.addAddress("10.0.0.2", 24);
    builder.addAddress(SS, 24);
   // builder.addAddress(SS,24);
    builder.addRoute("0.0.0.0",0);
    try {
        mInterface.close();
    } catch (Exception e) {
        // ignore
    }

    mInterface = builder.establish();
}}

问题出在这一行

mInterface = builder.setSession("GITVPN").setConfigureIntent(mConfigureIntent).establish();

Establish 返回 NULL,我似乎无法让它工作 我觉得地址有问题 我想在没有服务器的情况下工作,并且会有一个读取数据包的隧道 我看过其他一些帖子说我应该将地址设置为 10.0.0.2 而不是外部 ips (192.168.x.x),我应该添加路由 (0.0.0.0,0) 但是描述符文件一直返回 null,我似乎无法修复它 任何帮助将不胜感激,如果这听起来重复但我很抱歉,你们是我唯一的希望

【问题讨论】:

    标签: android sockets network-programming vpn datagram


    【解决方案1】:

    如果没有与您通信并将流量转发到互联网的服务器,您将无法运行 VpnService 并建立 VPN 连接。

    【讨论】:

      【解决方案2】:

      检查您分配给接口的 IP 地址,它不应与其他适配器相同。 builder操作的是一个TUN设备,它是为VPN服务而创建的。 因此,TUN 的 IP 地址应该设置得当。 使地址与他人冲突不是一个好主意。

      另外,您提到的第 3 步并不容易,因为 Android 不支持原始套接字。

      【讨论】:

      • 感谢您的回答我已经对这件事放弃了希望,无论我做什么都行不通
      【解决方案3】:

      只是为了恢复旧线程......

      • VpnService 需要用户交互才能开始,没有它就无法工作
      • ToyVpnClient 在屏幕上放置一个用户必须单击的按钮,完成后,Builder 方法将返回界面

      因此,使其工作的步骤是; 1. 在您的应用程序上构建一个按钮 2. 那个按钮的onclick,调用VpnService.prepare(this);(这=你的应用上下文) 3.Builder.establish()现在会返回一个VPN接口

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-08-31
        • 2020-04-22
        • 2012-10-23
        • 1970-01-01
        • 2012-11-14
        • 2016-11-01
        • 2021-04-14
        • 1970-01-01
        相关资源
        最近更新 更多