2016-06-23 33 views
0

我有一個遺留的java web應用程序,它可以調用外部web服務。該服務的提供商正在關閉TLS1.0支持。所以,我試圖看看應用程序如何繼續使用該服務。java 1.6使用代理的TLS1.2支持nginx/squid解決方案問題

我所看到的選項是:a)使用BouncyCastle的JCE而不是Java JCE http://boredwookie.net/index.php/blog/how-to-use-bouncy-castle-lightweight-api-s-tlsclient/,我想需要更改代碼/編譯(我們沒有這樣做的奢侈品)或2)使用代理服務器https://www.reddit.com/r/sysadmin/comments/48gzbi/proxy_solution_to_bump_tls_10_connection_to_tls_12/

我試過nginx代理 - 它似乎不處理終端服務器期望的TLS1.0傳入和TLS1.2之間的切換。

server { listen 443 ssl; server_name proxy.mydomain.com; 

ssl_certificate D:/apps/openssl/proxy.mydomain.com.cert; ssl_certificate_key D:/apps/openssl/proxy.mydomain.com.private; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers HIGH:SEED:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!RSAPSK:!aDH:!aECDH:!EDH-DSS-DES-CBC3-SHA:!KRB5- DES-CBC3-SHA:SRP; ssl_prefer_server_ciphers;

位置/ { proxy_pass https://fancyssl.hboeck.de/; }

由於https://fancyssl.hboeck.de僅支持TLS1.2,但與支持TLS1.0的https://www.google.com一起使用,因此502 /錯誤網關錯誤失敗。

我在Windows上這樣做。

回答

1

這不是TLSv1.2,它缺乏導致重新協商的SNI。

首先,我設置了nginx(1.8.1/Windows),並配置了類似你的配置,除了使用我自己的密鑰& cert和代理到我自己的測試服務器。它運行良好,從Java6請求者與TLSv1.0連接到服務器與TLSv1.2(甚至ECDHE-RSA-AES256GCM-SHA384,「最好」的密碼組之一)並返回頁面就好了。我試過fancyssl.hboek.de,得到了和你一樣的502。

With wireshark我看到nginx不會發送SNI(默認情況下)並且至少使用IPv4地址46.4.40.249(我沒有IPv6)該服務器顯然擁有多個域,因爲沒有SNI它提供了一個不同的(和過期!)證書,爲*.schokokeks.org,並且在第一個應用程序數據(請求)之後,它發送一個加密的握手(一個重新協商請求--nginx不承認)。使用openssl s_client進行測試,確認具有SNI的服務器立即發送頁面,但沒有重新協商;重新指定nginx爲openssl s_server確認如果服務器請求重新協商,沒有收到任何迴應,並關閉nginx將其視爲502.

我猜測Apache正在重新協商,因爲它意識到請求的主機未被證書覆蓋 - 除它再次使用'錯誤'的證書。我沒有試圖跟蹤那部分。

谷歌確實支持TLSv1.2工作(和ECDHE-RSA-AESGCM)當我連接,但即使沒有SNI不會重新談判,大概是因爲它的這種高容量沒有別的運行在www.google.com服務器和沒有歧義。我的測試服務器沒有虛擬主機,所以不需要SNI。

The nginx documentation reveals a directive proxy_ssl_server_name其中可以設置on啓用SNI,然後代理到這個服務器工作。

提示:該網頁上的一些聲明是錯誤的,儘管其結論(如果可能,使用TLSv1.2與ECDHE或DHE和AES-GCM)是好的。 另外,大部分 ssl_ciphers字符串都沒用,但你沒有問過這個問題。


ssl_ciphers HIGH:SEED:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!RSAPSK:!aDH:!aECDH:!EDH-DSS-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA:!SRP 

HIGH是一個良好的開端。

SEED在僅由Java/JSSE客戶端使用的服務器中沒有用處,因爲它沒有在Java端實現。即使在Java之外,它也只在韓國使用,在韓國它被創建作爲DES或IDEA的替代品,甚至在那裏它已經被ARIA替代 - 這是AES的替代品 - 但不是由OpenSSL和因此nginx。

aNULL可能是不需要的,因爲默認情況下,JSSE會禁用「匿名」套件,但這裏值得深入研究。

!eNULL什麼都不做;沒有eNULL套件在HIGHDEFAULT或甚至ALL。你只能明確地得到它們或者用奇怪的COMPLEMENTOFALL - 你不應該這樣做。

!EXPORT !DES !RC4什麼都不做;他們都沒有在HIGH。如果您在舊版本的OpenSSL或ALL上從DEFAULT開始,那麼它們會很好。

!PSK是不需要的; nginx似乎沒有配置爲PSK,而JSSE也沒有實現它。

!RSAPSK被忽略,因爲OpenSSL沒有實現該keyexchange,如果它確實已經覆蓋了上述那些套件。

!aDH !aECDH涵蓋!aNULL,因此什麼都不做。

!EDH-DSS-DES-CBC3-SHA很愚蠢;當您保留其他DHE_DSS和3DES套件時,沒有理由排除這一套件。

!KRB5-DES-CBC3-SHA被忽略,因爲OpenSSL沒有實現Kerberos,並且如果它確實沒有配置nginx再加上它再加上它將愚蠢的排除一個套件,同時保持相似。

!SRP是不需要的;像PSK nginx顯然不配置和JSSE不實現。

所以:HIGH:!aNULL是你所需要的。

+0

謝謝你的詳細解釋。我對此很陌生 - 不得不訴諸於此,因爲重新編譯代碼庫不是一種選擇。我能夠通過proxy_ssl_server_name on指令來訪問服務器。你提到我擁有的ssl_ciphers字符串是無用的。你能否詳細說明一下?如果可能,請分享你的nginx配置。 – shikarishambu

+0

@shikarishambu爲什麼重新編譯? Java字節碼向上兼容;我一直在j8上運行j6編譯的庫,沒有問題。除非你使用JNI? –

+0

感謝您的更新。我從你的回答中學到了很多東西。我不認爲java6代碼可以在沒有問題的較新的java版本中運行。無論如何,我嘗試了你所說的並且遇到了一些問題。這段代碼大約10歲 - 從java1開始。然後大約6年後,它又升到了java6。我有幾個選項可以嘗試。感謝您的幫助。 – shikarishambu