2015-01-16 7 views
12

मैं एक एसएसएल सॉकेट के साथ सर्वर से कनेक्ट करने के लिए जावा (एंड्रॉइड) का उपयोग करने की कोशिश कर रहा हूं। कृपया ध्यान दें कि यह HTTP डेटा नहीं है। यह टेक्स्ट और बाइनरी डेटा के मिश्रण के साथ मालिकाना प्रोटोकॉल है।एक HTTP प्रॉक्सी के माध्यम से एक एसएसएल सॉकेट कैसे कनेक्ट करें?

मैं उस HTTP कनेक्शन को HTTP प्रॉक्सी के माध्यम से रिले करना चाहता हूं, लेकिन मुझे इसके साथ कई समस्याएं आ रही हैं। अभी मैं जिस परिदृश्य का उपयोग करता हूं और मेरा ब्राउज़र स्क्विड प्रॉक्सी के साथ उपयोग करता है, वह

[क्लाइंट] -> [http कनेक्शन] -> [प्रॉक्सी] -> [एसएसएल कनेक्शन] -> [सर्वर]

यह ब्राउज़र के लिए काम करता है, क्योंकि प्रॉक्सी एसएसएल कनेक्शन बनाता है, तुरंत एक टीएलएस वार्ता होती है। हालांकि मेरा कोड ऐसा प्रतीत नहीं होता है।

final TrustManager[] trustManager = new TrustManager[] { new MyX509TrustManager() }; 
final SSLContext context = SSLContext.getInstance("TLS"); 
context.init(null, trustManager, null); 
SSLSocketFactory factory = context.getSocketFactory(); 
Socket s = factory.createSocket(new Socket(proxy_ip, 3128), hostName, port, true); 

मेरे पास जो समस्या है वह बनाता है सॉकेट कभी वापस नहीं आता है। प्रॉक्सी मशीन से वायरशर्क डंप के साथ, मैं देख सकता हूं कि प्रॉक्सी और सर्वर के बीच एक टीसीपी हैंडशेक होता है। वेब सत्रों से डंप के साथ, मैं देख सकता हूं कि क्लाइंट आमतौर पर इस बिंदु पर एक एसएसएल हैंडशेक शुरू करता है, जो मेरे परिदृश्य में नहीं होता है।

यह ट्रस्ट मैनेजर के साथ कोई समस्या नहीं है, क्योंकि प्रमाणपत्र कभी मेरे पास वापस नहीं आता है और यह कभी मान्य नहीं होता है।

संपादित करें:

चर्चा के बाद, इस कोड को मैं चलाने के लिए कोशिश कर रहा हूँ की अधिक पूर्ण संस्करण है। यह संस्करण सरल (नई सॉकेट (...)) के साथ ऊपर पैरामीटर है जैसा कि मैंने बाद में कोशिश की है।

कोड मैं डिबग करने के लिए कोशिश कर रहा हूँ के मूल संस्करण फेंकता
java.net.ConnectException: failed to connect to /192.168.1.100 (port 443): connect failed: ETIMEDOUT (Connection timed out)

अनुक्रम (एक सा फिर सरलीकृत) इस प्रकार है:

final Socket proxySocket = new Socket(); 
proxySocket.connect(proxyAddress, 2000); // 2 seconds as the connection timeout for connecting to the proxy server 
[Start a thread and write to outputStream=socket.getOutputStream()] 
final String proxyRequest = String.format("CONNECT %s:%d HTTP/1.1\r\nProxy-Connection: keep-alive\r\nConnection: keep-alive\r\nHost: %s:%d\r\n\r\n", hostName, port, hostName, port); 
outputStream.close(); // Closing or not doesn't change anything 
[Stop using that thread and let it exit by reaching the end of its main function] 

तो निम्नलिखित के साथ प्रतिक्रिया पढ़ने कोड:

final InputStreamReader isr = new InputStreamReader(proxySocket.getInputStream()); 
    final BufferedReader br = new BufferedReader(isr); 
    final String statusLine = br.readLine(); 

    boolean proxyConnectSuccess = false; 
    // readLine consumed the CRLF 
    final Pattern statusLinePattern = Pattern.compile("^HTTP/\\d+\\.\\d+ (\\d\\d\\d) .*"); 
    final Matcher statusLineMatcher = statusLinePattern.matcher(statusLine); 
    if (statusLineMatcher.matches()) 
    { 
     final String statusCode = statusLineMatcher.group(1); 
     if (null != statusCode && 0 < statusCode.length() && '2' == statusCode.charAt(0)) 
     { 
      proxyConnectSuccess = true; 
     } 
    } 

    // Consume rest of proxy response 
    String line; 
    while ("".equals((line = br.readLine())) == false) 
    { 
    } 

मैं कह सकता हूं कि यह कोड काम करता है क्योंकि यह SSL के बिना काम करता है। यहां बनाई गई सॉकेट, proxySocket वह है जो कि मेरे मूल उदाहरण की तरह फ्लाई पर एक नया निर्माण करने के बजाय createSocket फ़ंक्शन को पास किया गया है।

+0

java.net.Proxy HTTP के तहत काम नहीं करता। ऐसा लगता है कि सॉक्स प्रॉक्सी की आवश्यकता है। मुझे सूरज ओएस के लिए एक पैच मिला है लेकिन एंड्रॉइड के लिए कुछ भी नहीं है। यह महत्वपूर्ण है कि यह HTTP के लिए काम करता है क्योंकि एंड्रॉइड तृतीय पक्ष ऐप्स के बिना HTTPS/SOCKS समर्थन प्रदान नहीं कर सकता है (डिफ़ॉल्ट इंस्टॉल @ जनवरी 2015 को पर्याप्त कॉन्फ़िगरेशन प्रदान नहीं करता है)। – Eric

+0

यदि आप किसी HTTP प्रॉक्सी के माध्यम से किसी SSL सॉकेट से कनेक्ट कर रहे हैं, तो मैं संभवतः वेबकॉकेट पर विचार करने की सलाह दूंगा - विशेष रूप से त्रुटि संदेश "java.net.ConnectException: /192.168.1.100 (पोर्ट 443) से कनेक्ट करने में विफल रहा है" मानक HTTPS पोर्ट से कनेक्ट करने का प्रयास दिखाता है। बेशक, यह आपके उपयोग के मामले पर निर्भर करता है .... –

उत्तर

13

java.net.Proxy, या https.proxyHost/proxyPort गुण, केवल HttpURLConnection, नहीं के माध्यम से HTTP प्रॉक्सी का समर्थन एक Socket.

के माध्यम से अपने खुद की एक SSLSocket के लिए है कि काम करने के लिए, तुम सब एक प्लेन टेक्स्ट सॉकेट बनाने है, इस मुद्दे को एक HTTP CONNECT करने की जरूरत है इस पर आदेश, 200 के लिए प्रतिक्रिया की जांच करके एक SSLSocket.

संपादित में लपेट जब कनेक्ट आदेश भेजते समय, आप सॉकेट बंद नहीं करना चाहिए, निश्चित रूप से, और जब इसका उत्तर पढ़ते हैं तो आपको BufferedReader, का उपयोग नहीं करना चाहिए अन्यथा आप डेटा खो देंगे; या तो हाथ से लाइन को पढ़ें या इसके बहिष्कार के बावजूद DataInputStream.readLine(), का उपयोग करें। आपको आरएफसी 2616 पूरी तरह से पालन करने की आवश्यकता है।

1

मेरे पास अभी लक्षित लक्ष्य का परीक्षण/लिखने का समय नहीं है, हालांकि Upgrading socket to SSLSocket with STARTTLS: recv failed मूल समस्या को कवर करने लगता है।

आपके मामले में, आपको प्रॉक्सी से कनेक्ट करने, प्रॉक्सी कनेक्ट करने की आवश्यकता है, फिर कनेक्शन को अपग्रेड करना होगा - अनिवार्य रूप से आप संदर्भित प्रश्न में STARTTLS की जगह लेते हैं, और "670" की जांच की आवश्यकता नहीं है ।

+1

लेकिन इसके बजाय HTTP '200' की जांच की आवश्यकता है। – EJP

6

आपको javax.net lib का उपयोग करना होगा। आप javax.net.ssl ​​का उपयोग करके अपने लक्ष्य पर संग्रहीत कर सकते हैं। *

मुझे लगता है कि आप ऑरैकल दस्तावेज़ों का उपयोग करके समाधान प्राप्त कर सकते हैं। इसके लिए लिंक यहां दिया गया है।

SSLSocketClientWithTunneling

+2

उस लिंक में थोड़ी सी त्रुटि है। अनुरोध लाइनों में से एक को \ n, ''\ ​​r \ n' होना चाहिए – EJP

संबंधित मुद्दे