プロキシサーバー経由のHTTPS接続


103

プロキシサーバーを介したHTTPS接続は可能ですか?はいの場合、どの種類のプロキシサーバーがこれを許可しますか?

Apache HTTPクライアント4でSocks 5プロキシを使用する方法と重複していますか?



はい、可能です。実用的な例は、ここを参照してください stackoverflow.com/questions/56981993/...
リック・

回答:


66

TLS / SSL(HTTPSのS)は、ユーザーと接続しているサーバーの間に盗聴者、つまりプロキシがないことを保証します。通常はCONNECT、プロキシを介してTCP接続を開くために使用します。この場合、プロキシは要求/応答をキャッシュ、読み取り、または変更することができないため、かなり役に立たなくなります。

プロキシーが情報を読み取れるようにしたい場合は、以下のアプローチをとることができます。

  1. クライアントがHTTPSセッションを開始します
  2. プロキシは透過的に接続をインターセプトし、クライアントによって無条件に信頼されている認証局によって署名された、アドホックに生成された(おそらく弱い)証明書K aを返します。
  3. プロキシはターゲットへのHTTPSセッションを開始します
  4. プロキシはSSL証明書の整合性を検証します。証明書が有効でない場合、エラーが表示されます。
  5. プロキシはコンテンツをストリーミングし、それを復号化し、K aで再暗号化します
  6. クライアントはものを表示します

SquidのSSLバンプがその例です。同様に、げっぷはこれを行うように構成できます。これは、エジプトのISPによって、より無害なコンテキストで使用されています

最新のWebサイトおよびブラウザーは、このアプローチを無効にするHPKPまたは組み込みの証明書ピンを使用できることに注意してください。


13
これは原則的には機能しますが、ブラウザがHTTPSリクエストのHTTPプロキシと通信する方法ではありません。ここで説明する方法は、プロキシサーバーが実質的に中間者であることを意味します(したがって、それに応じて信頼する必要があります)。
ブルーノ

5
Squidはこれを行います。SSL Bumpと呼ばれています。
Adam Mackler 2013

3
エンドユーザーへの多くの警告がないと機能しません。「無条件にクライアントから信頼されている」-そのようなことはありません。証明書が完全なAAA +++である場合でも、エンドユーザーが要求したものと一致しない別のドメインが表示されます。もちろん、SSLチェックを無効にするパラメーターを指定してwgetを使用することは可能ですが、どうでしょう?コアセキュリティチェックが無効になっていると、この接続に「SSL」という名前を付けることはできません。
Van Jone、2015年

1
@Van Jone Unconditionally trustedはCA証明書を指します。CA証明書にはドメインがありません。これは、ユーザーへの警告なしに実際に機能する、または機能しない2つの例で回答を修正しました。
phihag 2015年

6
私の答えは、「偽のCA」と呼ばれるものに依存しています。CAの証明書無条件に信頼されます。これは、ユーザー(またはコンピューター上のソフトウェア(エンタープライズ構成やマルウェアなど))がそのように構成したか、CAが主要なブラウザーによって信頼されたCAの1つから取得されたためです。 MCSの場合。プロキシは、クライアントが要求するすべてのドメインに対して新しい有効な証明書を生成します。そのため、回答の最後に記載されているMIT対策機能がなければ、クライアントは気づきません。
phihag 2015年

22

簡単に言えば、これは可能であり、特別なHTTPプロキシまたはSOCKSプロキシを使用して実行できます。

何よりもまず、HTTPSはSSL / TLSを使用します。これは、設計上、安全でない通信チャネル上に安全な通信チャネルを確立することにより、エンドツーエンドのセキュリティを保証します。HTTPプロキシがコンテンツを見ることができる場合、それは中間者盗聴者であり、これはSSL / TLSの目標を打ち破ります。したがって、プレーンなHTTPプロキシを介してプロキシする場合は、いくつかのトリックが実行されている必要があります。

コツは、という名前の特別なコマンドを使用して、HTTPプロキシをTCPプロキシに変換することCONNECTです。すべてのHTTPプロキシがこの機能をサポートしているわけではありませんが、現在多くのプロキシがサポートしています。TCPプロキシはHTTPコンテンツがクリアテキストで転送されているのを確認できませんが、パケットを前後に転送する機能には影響しません。このようにして、クライアントとサーバーはプロキシの助けを借りて相互に通信できます。これは、HTTPSデータをプロキシする安全な方法です。

これを行うには、HTTPプロキシが中間者になる安全でない方法もあります。クライアントが開始した接続を受信し、実サーバーへの別の接続を開始します。適切に実装されたSSL / TLSでは、プロキシは実サーバーではないことがクライアントに通知されます。したがって、クライアントは、正常に機能するための警告を無視して、プロキシを信頼する必要があります。その後、プロキシは1つの接続からのデータを復号化し、再暗号化してもう一方にフィー​​ドします。

最後に、我々は通じHTTPSプロキシ確かにすることができますSOCKSプロキシSOCKSために低いレベルでのプロキシ作品。SOCKSプロキシは、TCPプロキシとUDPプロキシの両方と考えることができます。


CONNECTを使用すると、stackoverflow.com / a / 3118759/632951に記載されているセキュリティ警告が発生しますか?
パセリエ

@Pacerier私はそうは思いません。CONNECTモードでは、プロキシはトランスポート層で機能します。
サイカー、2017年

では、CONNECTメソッドを使用すると、クライアントからのhttpsデータが中間プロキシのアプリケーションレベル渡されません。そして、プロキシのTCPレベルで評価され、リモートサーバーに直接中継されましたか?
-zzinny

15

私が覚えている限り、プロキシでHTTP CONNECTクエリを使用する必要があります。これにより、要求接続が透過的なTCP / IPトンネルに変換されます。

そのため、使用するプロキシサーバーがこのプロトコルをサポートしているかどうかを知る必要があります。


3
実際、クライアントはCONNECT動詞を使用して、HTTPプロキシサーバー経由でhttps:// URIを使用します。この場合、接続はプロキシを介してトンネリングされるため、クライアントがエンドサーバーと直接通信しているかのように、証明書の検証は通常どおり行われます。
Bruno

1
@chburd、しかしプロキシは通常HTTP CONNECTをサポートしますか?
Pacerier 2017年

9

まだ興味がある場合は、同様の質問に対する回答を示し ます。TwistedでHTTPプロキシをHTTPSプロキシに変換します。

質問の2番目の部分に答えるには:

はいの場合、どの種類のプロキシサーバーがこれを許可しますか?

デフォルトでは、ほとんどのプロキシサーバーはポート443へのHTTPS接続のみを許可するように構成されているため、カスタムポートを含むhttps URIは機能しません。これは、プロキシサーバーに応じて、通常は構成可能です。たとえば、SquidとTinyProxyはこれをサポートしています。


5

SOCKSプロキシを使用してHTTPリクエストとHTTPSリクエストの両方をサポートする完全なJavaコードを次に示します。

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.Socket;
import java.nio.charset.StandardCharsets;

import org.apache.http.HttpHost;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.protocol.HttpContext;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;

import javax.net.ssl.SSLContext;

/**
 * How to send a HTTP or HTTPS request via SOCKS proxy.
 */
public class ClientExecuteSOCKS {

    public static void main(String[] args) throws Exception {
        Registry<ConnectionSocketFactory> reg = RegistryBuilder.<ConnectionSocketFactory>create()
            .register("http", new MyHTTPConnectionSocketFactory())
            .register("https", new MyHTTPSConnectionSocketFactory(SSLContexts.createSystemDefault
                ()))
            .build();
        PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(reg);
        try (CloseableHttpClient httpclient = HttpClients.custom()
            .setConnectionManager(cm)
            .build()) {
            InetSocketAddress socksaddr = new InetSocketAddress("mysockshost", 1234);
            HttpClientContext context = HttpClientContext.create();
            context.setAttribute("socks.address", socksaddr);

            HttpHost target = new HttpHost("www.example.com/", 80, "http");
            HttpGet request = new HttpGet("/");

            System.out.println("Executing request " + request + " to " + target + " via SOCKS " +
                "proxy " + socksaddr);
            try (CloseableHttpResponse response = httpclient.execute(target, request, context)) {
                System.out.println("----------------------------------------");
                System.out.println(response.getStatusLine());
                System.out.println(EntityUtils.toString(response.getEntity(), StandardCharsets
                    .UTF_8));
            }
        }
    }

    static class MyHTTPConnectionSocketFactory extends PlainConnectionSocketFactory {
        @Override
        public Socket createSocket(final HttpContext context) throws IOException {
            InetSocketAddress socksaddr = (InetSocketAddress) context.getAttribute("socks.address");
            Proxy proxy = new Proxy(Proxy.Type.SOCKS, socksaddr);
            return new Socket(proxy);
        }
    }

    static class MyHTTPSConnectionSocketFactory extends SSLConnectionSocketFactory {
        public MyHTTPSConnectionSocketFactory(final SSLContext sslContext) {
            super(sslContext);
        }

        @Override
        public Socket createSocket(final HttpContext context) throws IOException {
            InetSocketAddress socksaddr = (InetSocketAddress) context.getAttribute("socks.address");
            Proxy proxy = new Proxy(Proxy.Type.SOCKS, socksaddr);
            return new Socket(proxy);
        }
    }
}


3

SSHを介したHTTPSのトンネリング(Linuxバージョン):

1) turn off using 443 on localhost
2) start tunneling as root: ssh -N login@proxy_server -L 443:target_ip:443
3) adding 127.0.0.1 target_domain.com to /etc/hosts

localhostで行うすべてのこと。次に:

target_domain.com is accessible from localhost browser.

1

私は試しました

  • トンネリングを開始します。 ssh -N -D 12345 login@proxy_server
  • Firefoxの設定でプロキシを設定する localhost:12345
    • そして「すべてのプロトコルにこのプロキシを使用する」にチェックを入れます

しかし、これにより、https Webサイトに接続しようとすると、常に「安全でない接続」というエラーが発生しました。

解決策は

  • 「このプロキシをすべてのプロトコルに使用する」のチェックを外します
  • プロキシ「localhost:12345」をSOCKSプロキシとしてのみ設定します
  • HTTPプロキシ、SSLプロキシ、FTPプロキシは空白のままにします

デジタルオーシャンドキュメンテーションからの参照

SOCKSトンネルを使用してVPNなしでWebトラフィックを安全にルーティングする方法


1

「プロキシサーバーを介してHTTPS接続を行う」とは、中間者攻撃タイプのプロキシサーバーを意味するとは思いません。TLS経由でhttpプロキシサーバーに接続できるかどうかを尋ねていると思います。そして答えはイエスです。


プロキシサーバーを介したHTTPS接続は可能ですか?

はい、私の質問と回答をご覧ください。HTTPsプロキシサーバーはSwitchOmegaでのみ機能します

はいの場合、どの種類のプロキシサーバーがこれを許可しますか?

この種のプロキシサーバーは、通常のWebサイトと同様にSSL証明書を展開します。ただしpac、SSL経由のプロキシ接続を構成するためのファイルが必要です。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.