我会尝试尽可能具有描述性 我是android的新手,我正在制作一个Android应用程序 在该应用程序中,我希望能够看到从移动设备发出的HTTP请求的地址(在他们前往的网站上)。 所以我环顾四周,我发现要做到这一点,我需要使用VPN和Android 4.0+有一个由谷歌提供的VPNService使用ToyVPNService实现 所以我得到了这项服务,并开始改变它,所以我可以使用它而无需使用服务器 我想按如下方式使用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,我似乎无法修复它 任何帮助将不胜感激,如果这听起来有点重复,我感到非常抱歉,但我超级卡住,你们是我唯一的希望
答案 0 :(得分:1)
如果没有与之通信的服务器并且将流量转发到互联网,则无法运行VpnService并建立VPN连接。
答案 1 :(得分:1)
检查您分配给接口的IP地址,它不应与其他适配器相同。 构建器运行的是TUN设备,它是为VPN服务创建的。 因此,应该正确设置TUN的IP地址。 让地址与他人发生冲突不是一个好主意。
另外,你提到的第3步并不容易,因为Android不支持原始套接字。
答案 2 :(得分:0)
只是为了恢复一个旧线程...
VpnService
需要用户互动才能开始,并且在没有它的情况下无法工作ToyVpnClient
在屏幕上放置一个用户必须点击的按钮,一旦完成,Builder方法将返回界面所以,让它发挥作用的步骤是;
1.在您的应用上构建一个按钮
2. onclick
该按钮,调用VpnService.prepare(this);
(这=您的应用内容)
3. Builder.establish()
现在将返回VPN接口