为什么我的TCP连接会锁定OpenVPN?

时间:2016-10-07 13:07:12

标签: java android sockets ssl tcp

问题

我正在通过TCP连接从Android 4.4.4客户端向使用java.net.socket和javax.net.ssl.SSLSocket的服务器传输1Mb到100Mb的文件。如果没有OpenVPN,它会按预期工作,但是随着它的运行,java.net.socket TCP连接会在每次结束时锁定,而javax.net.ssl.SSLSocket有时会锁定。 我目前解决这个问题的方法是在客户端将“缓冲区大小”更改为10个字节(请参阅代码)。 我已经尝试在OpenVPN配置文件中更改MTU,MSSFIX和FRAGMENT值。

设置

我使用兼容WiFi的路由器建立了本地网络。路由器未连接到Internet。我的Android客户端通过WiFi连接。我有一个eth连接到我的计算机,我正在运行我的java服务器和Xubuntu在virtualbox上使用openvpn。 Virtualbox与桥接适配器连接。 Android客户端可以连接到openvpn服务器,并可以ping网络上的其他客户端。所有机器上的当前MTU为1500(默认值)。

目标

我正在测试OpenVPN对纯文本和安全套接字连接的时间影响。

问题

  1. 为什么我的纯文本传输每次都失败,但安全套接字传输有时会失败?
  2. 为什么更改“缓冲区大小”可以解决我的问题?
  3. 如果我将“缓冲区大小”设置为10个字节并通过安全套接字发送数据,我将在服务器端收到10个字节。但是,如果我通过普通套接字发送具有相同缓冲区大小的数据,则会收到超过10个字节。这是填充的结果吗?
  4. 有没有更好的方法通过套接字将数据从Android传输到服务器?
  5. 客户端代码(纯文本)

    protected void nonsecure_transfer(String ip, int port, int fileno) {
    
            Socket sock;
    
            try {
                sock = new Socket(ip, port);
    
                // sendfile
                final InputStream is;
                switch (fileno){
                    case 0:
                        is = getResources().openRawResource(R.raw.test1mb);
                        break;
                    case 1:
                        is = getResources().openRawResource(R.raw.test10mb);
                        break;
                    case 2:
                        is = getResources().openRawResource(R.raw.test100mb);
                        break;
                    default: is = getResources().openRawResource(R.raw.test1mb);
                        break;
                }
                BufferedOutputStream os = new BufferedOutputStream(sock.getOutputStream());
                int buffer_size = Integer.parseInt(buffersize.getText().toString());
                byte buffer[] = new byte[buffer_size];
                int count = 0;
                while ((count = is.read(buffer)) > 0) {
                    os.write(buffer, 0, count);
                }
                os.flush();
                sock.close();
            } catch (UnknownHostException e) {
                log.append("Error \n" + e);
            } catch (IOException e) {
                log.append("Error \n" + e);
    
            }
    

    服务器代码(纯文本)

    protected void handleConnection(Socket server) throws Exception {
            InputStream is = server.getInputStream();
            FileOutputStream fos = new FileOutputStream(...);
            BufferedOutputStream bos = new BufferedOutputStream(fos);
    
            byte buffer[] = new byte[8129];
            int count = 0;
            int size = 0;
            while ((count = is.read(buffer)) > 0)
            {
                bos.write(buffer, 0, count);
            }
            bos.flush();
            bos.close();
            is.close();
        }
    

    客户端代码(安全)

    protected void secure_transfer(String ip, int port, int fileno) throws IOException, CertificateException, NoSuchAlgorithmException, UnrecoverableKeyException, KeyStoreException, KeyManagementException {
    
            String passphrase = "test123";
    
            KeyStore ks = KeyStore.getInstance("BKS");
            InputStream keyin = getResources().openRawResource(R.raw.server_keystore);
            ks.load(keyin, "test123".toCharArray());
    
            TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
            tmf.init(ks);
    
            KeyStore clientKeyStore = KeyStore.getInstance("BKS");
            clientKeyStore.load(getResources().openRawResource(R.raw.client_keystore), passphrase.toCharArray());
    
            KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
            kmf.init(clientKeyStore, passphrase.toCharArray());
    
            SSLContext sslContext = SSLContext.getInstance("TLS");
            sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), new SecureRandom());
            SSLSocketFactory socketFactory = sslContext.getSocketFactory();
            SSLSocket socket = (SSLSocket)
                    socketFactory.createSocket(new Socket(ip, port), ip, port, false);
            socket.startHandshake();
            try {
    
                // sendfile
                final InputStream is;
                switch (fileno){
                    case 0:
                        is = getResources().openRawResource(R.raw.test1mb);
                        break;
                    case 1:
                        is = getResources().openRawResource(R.raw.test10mb);
                        break;
                    case 2:
                        is = getResources().openRawResource(R.raw.test100mb);
                        break;
                    default: is = getResources().openRawResource(R.raw.test1mb);
                        break;
                }
                BufferedOutputStream os = new BufferedOutputStream(socket.getOutputStream());
                int buffer_size = Integer.parseInt(buffersize.getText().toString());
                byte buffer[] = new byte[buffer_size];
                int count = 0;
                while ((count = is.read(buffer)) > 0) {
                    os.write(buffer, 0, count);
                }
                os.flush();
                socket.close();
            } catch (UnknownHostException e) {
                log.append("Error \n" + e);
            } catch (IOException e) {
                log.append("Error \n" + e);
    
            }
        }
    

    服务器代码(安全)

    public void listen() throws Exception {
            try {
    
                String passphrase = "test123";
    
                KeyStore ks = KeyStore.getInstance("JKS");
                ks.load(new FileInputStream("server_keystore.jks"),"test123".toCharArray());
                KeyManagerFactory kmf =
                        KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
                kmf.init(ks, "test123".toCharArray());
    
                SSLContext sslcontext =
                        SSLContext.getInstance("TLS");
    
                sslcontext.init(kmf.getKeyManagers(), null, null);
    
                ServerSocketFactory ssf =
                        sslcontext.getServerSocketFactory();
    
    
                SSLServerSocket serverSocket = (SSLServerSocket)
                        ssf.createServerSocket(9999);
    
                while (true) {
                    SSLSocket s = (SSLSocket) serverSocket.accept();
                    handleConnection(s);
                    s.close();
                }
    
            } catch (IOException ioe) {
                System.out.println("IOException: " + ioe);
                ioe.printStackTrace();
                System.exit(1);
            } catch (GeneralSecurityException e) {
                System.out.println("GeneralSecurityException: " + e);
                e.printStackTrace();
                System.exit(1);
            }
        }
    
        int packet = 0;
        protected void handleConnection(Socket server) throws Exception {
            InputStream is = server.getInputStream();
            FileOutputStream fos = new FileOutputStream(...);
            BufferedOutputStream bos = new BufferedOutputStream(fos);
    
            byte buffer[] = new byte[8129];
            int count = 0;
            int size = 0;
            while ((count = is.read(buffer)) > 0)
            {
                bos.write(buffer, 0, count);
            }
            bos.flush();
            bos.close();
            is.close();
        }
    

    OpenVPN config

    port 1194
    proto udp
    
    dev tun
    ca ca.crt
    cert server.crt
    key server.key  # This file should be kept secret
    dh dh2048.pem
    
    push "redirect-gateway def1 bypass-dhcp"
    push "dhcp-option DNS 208.67.222.222"
    push "dhcp-option DNS 208.67.220.220"
    ;client-to-client
    ;duplicate-cn
    keepalive 10 120
    
    tls-auth ta.key 0 # This file is secret
    key-direction 0
    cipher AES-128-CBC   # AES
    
    auth SHA256
    ;comp-lzo
    
    persist-key
    persist-tun
    
    mssfix 1500
    

    链接信息(xubuntu - openvpn)

    enp0s3    Link encap:Ethernet  HWaddr 08:00:27:19:55:dc  
              inet addr:192.168.1.216  Bcast:192.168.1.255  Mask:255.255.255.0
              inet6 addr: fdbb:8432:3a7c:0:3290:af79:3a93:dcfd/64 Scope:Global
              inet6 addr: fe80::c133:9666:4062:e40f/64 Scope:Link
              inet6 addr: fdbb:8432:3a7c::52c/128 Scope:Global
              inet6 addr: fdbb:8432:3a7c:0:f8b3:90c2:1d8f:f21e/64 Scope:Global
              UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
              RX packets:162659 errors:0 dropped:0 overruns:0 frame:0
              TX packets:63868 errors:0 dropped:0 overruns:0 carrier:0
              collisions:0 txqueuelen:1000 
              RX bytes:214361110 (214.3 MB)  TX bytes:18496915 (18.4 MB)
    
    tun0      Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00  
              inet addr:10.8.0.1  P-t-P:10.8.0.2  Mask:255.255.255.255
              UP POINTOPOINT RUNNING NOARP MULTICAST  MTU:1500  Metric:1
              RX packets:9932 errors:0 dropped:0 overruns:0 frame:0
              TX packets:7518 errors:0 dropped:0 overruns:0 carrier:0
              collisions:0 txqueuelen:100 
              RX bytes:13666203 (13.6 MB)  TX bytes:423228 (423.2 KB)
    

    链接信息(java服务器)

    en1: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
        ether 00:26:08:e8:d3:36 
        inet 192.168.1.194 netmask 0xffffff00 broadcast 192.168.1.255
        media: autoselect
        status: active
    

0 个答案:

没有答案
相关问题