连接到隧道后无法浏览任何内容

Posted

技术标签:

【中文标题】连接到隧道后无法浏览任何内容【英文标题】:Can not browse anything after connecting to a tunnel 【发布时间】:2020-11-10 15:14:23 【问题描述】:

所以,我正在阅读使用应用程序从这里guide 连接到 *** 的指南 .我真正想要的是通过使用互联网上的免费 DNS 来制作我自己的 *** 应用程序。因为我想要 DoH(通过 Https 的 DNS)和完全的安全性。所以,我希望 CleanBrowsing 成为我的 DNS。 (我知道已经有一个应用程序,但我想从头开始)。所以我去了这个CleanBrowsing DNS GUIDE。我正在使用他们提供的以下免费过滤器

family-filter-dns.cleanbrowsing.org

所以,我可以将我的隧道连接到服务器,但是当我打开浏览器时,它什么也没做。这里是迷你版的配置。

final SocketAddress serverAddress = new InetSocketAddress("family-filter-dns.cleanbrowsing.org", 53);

***Service.Builder builder = mService.new Builder();

    builder.addAddress("10.1.10.1", 32);
    builder.addDnsServer("185.228.168.168");
    builder.addDnsServer("9.9.9.9");
    builder.addRoute("0.0.0.0", 0);
    builder.setMtu(1000);

我的完整文件如下所示

 public Toy***Connection(final ***Service service, final int connectionId,
                            final String serverName, final int serverPort, final byte[] sharedSecret,
                            final String proxyHostName, final int proxyHostPort, boolean allow,
                            final Set<String> packages) 
        mService = service;
        mConnectionId = connectionId;

        mServerName = serverName;
        mServerPort = serverPort;
        mSharedSecret = sharedSecret;

        if (!TextUtils.isEmpty(proxyHostName)) 
            mProxyHostName = proxyHostName;
        
        if (proxyHostPort > 0) 
            // The port value is always an integer due to the configured inputType.
            mProxyHostPort = proxyHostPort;
        
        mAllow = allow;
        mPackages = packages;
    

    /**
     * Optionally, set an intent to configure the ***. This is @code null by default.
     */
    public void setConfigureIntent(PendingIntent intent) 
        mConfigureIntent = intent;
    

    public void setOnEstablishListener(OnEstablishListener listener) 
        mOnEstablishListener = listener;
    

    @Override
    public void run() 
        try 
            Log.i(getTag(), "Starting");

            // If anything needs to be obtained using the network, get it now.
            // This greatly reduces the complexity of seamless handover, which
            // tries to recreate the tunnel without shutting down everything.
            // In this demo, all we need to know is the server address.
            final SocketAddress serverAddress = new InetSocketAddress("family-filter-dns.cleanbrowsing.org", 53);

            // We try to create the tunnel several times.
            // TODO: The better way is to work with ConnectivityManager, trying only when the
            // network is available.
            // Here we just use a counter to keep things simple.
//            for (int attempt = 0; attempt < 10; ++attempt) 
            // Reset the counter if we were connected.
            if (run(serverAddress)) 
//                    attempt = 0;
            

//                 Sleep for a while. This also checks if we got interrupted.
//                Thread.sleep(3000);
//            
            Log.i(getTag(), "Giving up");
         catch (IOException | InterruptedException | IllegalArgumentException e) 
            Log.e(getTag(), "Connection failed, exiting", e);
        
    

    private static final String TAG = "Toy***Connection";

    private boolean run(SocketAddress server)
            throws IOException, InterruptedException, IllegalArgumentException 
        ParcelFileDescriptor iface = null;
        boolean connected = false;
        // Create a DatagramChannel as the *** tunnel.
        try (DatagramChannel tunnel = DatagramChannel.open()) 

            // Protect the tunnel before connecting to avoid loopback.
            if (!mService.protect(tunnel.socket())) 
                throw new IllegalStateException("Cannot protect the tunnel");
            

            // Connect to the server.
            tunnel.connect(server);
            Log.d(TAG, "run: connected to the tunnel");

            // For simplicity, we use the same thread for both reading and
            // writing. Here we put the tunnel into non-blocking mode.
            tunnel.configureBlocking(false);

            // Authenticate and configure the virtual network interface.
            iface = configure("");

            // Now we are connected. Set the flag.
            connected = true;

            // Packets to be sent are queued in this input stream.
            FileInputStream in = new FileInputStream(iface.getFileDescriptor());

            // Packets received need to be written to this output stream.
            FileOutputStream out = new FileOutputStream(iface.getFileDescriptor());

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

            // Timeouts:
            //   - when data has not been sent in a while, send empty keepalive messages.
            //   - when data has not been received in a while, assume the connection is broken.
            long lastSendTime = System.currentTimeMillis();
            long lastReceiveTime = System.currentTimeMillis();

            // 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) 
                    // Write the outgoing packet to the tunnel.
                    packet.limit(length);
                    tunnel.write(packet);
                    packet.clear();

                    // There might be more outgoing packets.
                    idle = false;
                    lastReceiveTime = System.currentTimeMillis();
                

                // Read the incoming packet from the tunnel.
                length = tunnel.read(packet);
                if (length > 0) 
                    // Ignore control messages, which start with zero.
                    if (packet.get(0) != 0) 
                        // Write the incoming packet to the output stream.
                        out.write(packet.array(), 0, length);
                    
                    packet.clear();

                    // There might be more incoming packets.
                    idle = false;
                    lastSendTime = System.currentTimeMillis();
                

                // If we are idle or waiting for the network, sleep for a
                // fraction of time to avoid busy looping.
                if (idle) 
                    Thread.sleep(IDLE_INTERVAL_MS);
                    final long timeNow = System.currentTimeMillis();

                    if (lastSendTime + KEEPALIVE_INTERVAL_MS <= timeNow) 
                        // We are receiving for a long time but not sending.
                        // Send empty control messages.
                        packet.put((byte) 0).limit(1);
                        for (int i = 0; i < 3; ++i) 
                            packet.position(0);
                            tunnel.write(packet);
                        
                        packet.clear();
                        lastSendTime = timeNow;
                     else if (lastReceiveTime + RECEIVE_TIMEOUT_MS <= timeNow) 
                        // We are sending for a long time but not receiving.
                        throw new IllegalStateException("Timed out");
                    
                
            
         catch (SocketException e) 
            Log.e(getTag(), "Cannot use socket", e);
         finally 
            if (iface != null) 
                try 
                    iface.close();
                 catch (IOException e) 
                    Log.e(getTag(), "Unable to close interface", e);
                
            
        
        return connected;
    

    private ParcelFileDescriptor handshake(DatagramChannel tunnel)
            throws IOException, InterruptedException 
        // To build a secured tunnel, we should perform mutual authentication
        // and exchange session keys for encryption. To keep things simple in
        // this demo, we just send the shared secret in plaintext and wait
        // for the server to send the parameters.

        // Allocate the buffer for handshaking. We have a hardcoded maximum
        // handshake size of 1024 bytes, which should be enough for demo
        // purposes.
        ByteBuffer packet = ByteBuffer.allocate(1024);

        // Control messages always start with zero.
        packet.put((byte) 0).put(mSharedSecret).flip();

        // Send the secret several times in case of packet loss.
        for (int i = 0; i < 3; ++i) 
            packet.position(0);
            tunnel.write(packet);
        
        packet.clear();


        return configure(new String());

        // Wait for the parameters within a limited time.
//        for (int i = 0; i < MAX_HANDSHAKE_ATTEMPTS; ++i) 
//            Thread.sleep(IDLE_INTERVAL_MS);
//
//            // Normally we should not receive random packets. Check that the first
//            // byte is 0 as expected.
//            int length = tunnel.read(packet);
//            if (length > 0 && packet.get(0) == 0) 
//
//            
//        
//        throw new IOException("Timed out");
    

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    private ParcelFileDescriptor configure(String parameters) throws IllegalArgumentException 
        // Configure a builder while parsing the parameters.
        ***Service.Builder builder = mService.new Builder();


        builder.addAddress("10.1.10.1", 32);
//        builder.addAddress("185.228.148.168", 32);
//        builder.addAddress("192.168.1.1", 24);

        builder.addDnsServer("185.228.168.168");
        builder.addDnsServer("9.9.9.9");
        builder.addRoute("0.0.0.0", 0);
        builder.setMtu(1000);


        // Create a new interface using the builder and save the parameters.
        final ParcelFileDescriptor ***Interface;


        try 
            builder.addDisallowedApplication("com.example.android.toy***");
         catch (PackageManager.NameNotFoundException e) 
            Log.w(getTag(), "Package not available: " + "packageName", e);
        

//        for (String packageName : mPackages) 
//            try 
//                if (mAllow) 
//                    builder.addAllowedApplication(packageName);
//                 else 
//
//                
//             catch (PackageManager.NameNotFoundException e)
//
//            
//        


        builder.setSession(mServerName).setConfigureIntent(mConfigureIntent);
        if (!TextUtils.isEmpty(mProxyHostName)) 
//            builder.setHttpProxy(ProxyInfo.buildDirectProxy(mProxyHostName, mProxyHostPort));
        
        synchronized (mService) 
            ***Interface = builder.establish();


            if (mOnEstablishListener != null) 
                mOnEstablishListener.onEstablish(***Interface);
            
        
        Log.i(getTag(), "New interface: " + ***Interface + " (" + parameters + ")");
        return ***Interface;
    

    private final String getTag() 
        return Toy***Connection.class.getSimpleName() + "[" + mConnectionId + "]";
    

【问题讨论】:

【参考方案1】:

更改路由地址:

builder.addRoute("10.1.10.0", 32);

【讨论】:

以上是关于连接到隧道后无法浏览任何内容的主要内容,如果未能解决你的问题,请参考以下文章

如何只允许隧道连接到端口?

通过 JSch 建立 SSH 隧道

无法使用 JDBC 连接通过 SSH 隧道连接到 Azure DB

无法通过 python 中的 ssh 隧道连接到远程数据库

使用 SSH 隧道时无法通过套接字错误连接到本地 MySQL 服务器

创建一个连接到其他网站的网站?