Connexions HTTPS sur des serveurs proxy

Réponses:

66

TLS / SSL (Le S en HTTPS) garantit qu'il n'y a pas d'espionnage entre vous et le serveur que vous contactez, c'est-à-dire pas de mandataires. Normalement, vous utilisez CONNECTpour ouvrir une connexion TCP via le proxy. Dans ce cas, le proxy ne pourra pas mettre en cache, lire ou modifier les requêtes / réponses, et donc être plutôt inutile.

Si vous souhaitez que le proxy puisse lire les informations, vous pouvez adopter l'approche suivante:

  1. Le client démarre la session HTTPS
  2. Le proxy intercepte la connexion de manière transparente et renvoie un certificat généré ad hoc (éventuellement faible) K a , signé par une autorité de certification qui est inconditionnellement approuvé par le client.
  3. Le proxy démarre la session HTTPS pour cibler
  4. Le proxy vérifie l'intégrité du certificat SSL; affiche une erreur si le certificat n'est pas valide.
  5. Le proxy diffuse le contenu, le déchiffre et le re-crypte avec K a
  6. Le client affiche des éléments

Un exemple est la bosse SSL de Squid . De même, burp peut être configuré pour ce faire. Cela a également été utilisé dans un contexte moins bénin par un FAI égyptien .

Notez que les sites Web et les navigateurs modernes peuvent utiliser HPKP ou des broches de certificat intégrées qui vont à l'encontre de cette approche.

Phihag
la source
13
Cela pourrait fonctionner en principe, mais ce n'est pas ainsi que les navigateurs communiquent avec les proxys HTTP pour les requêtes HTTPS. La façon dont il est décrit ici implique que le serveur proxy est en fait un homme du milieu (il faudrait donc lui faire confiance en conséquence).
Bruno
5
Squid fait ça. Cela s'appelle SSL Bump .
Adam Mackler
3
Ne fonctionnera pas sans beaucoup d'alerte pour l'utilisateur final. "une confiance inconditionnelle du client" - il n'y a rien de tel. Même si le certificat est parfait-AAA +++, il montre toujours un domaine différent ne correspondant pas à ce que l'utilisateur final a demandé, ce qui fera sauter n'importe quel navigateur sensé (ne signifie pas IE ici ...) de haut en bas en hurlant. Bien sûr, il est possible d'utiliser wget avec des paramètres désactivant les contrôles SSL, mais devinez quoi? cette connexion ne peut plus être nommée "SSL" après la désactivation de ses contrôles de sécurité de base.
Van Jone
1
@Van Jone Unconditionally trustedfait référence à un certificat CA. Les certificats d'autorité de certification n'ont pas de domaine. J'ai modifié la réponse avec deux exemples où cela fonctionne / a fonctionné dans la pratique sans aucune alerte à l'utilisateur.
phihag
6
Ma réponse repose sur ce que vous appelez une "fausse CA". Le certificat de l'autorité de certification est approuvé de manière inconditionnelle, soit parce que l'utilisateur (ou un logiciel sur son ordinateur, par exemple une configuration d'entreprise ou un logiciel malveillant) l'a configuré de cette façon, soit parce que l'autorité de certification a été obtenue auprès de l'une des autorités de certification approuvées par les principaux navigateurs, comme dans l'affaire MCS. Le proxy génère un nouveau certificat valide pour chaque domaine que le client demande, donc sans les fonctionnalités anti-MITM mentionnées à la fin de la réponse, le client ne le remarquera pas.
phihag
23

La réponse courte est: c'est possible et peut être fait avec un proxy HTTP spécial ou un proxy SOCKS.

Tout d'abord, HTTPS utilise SSL / TLS qui, de par sa conception, assure la sécurité de bout en bout en établissant un canal de communication sécurisé sur un canal non sécurisé. Si le proxy HTTP est capable de voir le contenu, alors c'est un homme du milieu qui écoute et cela va à l'encontre de l'objectif de SSL / TLS. Donc, il doit y avoir quelques astuces en cours de lecture si nous voulons proxy via un proxy HTTP simple.

L'astuce est que nous transformons un proxy HTTP en proxy TCP avec une commande spéciale nommée CONNECT. Tous les proxys HTTP ne prennent pas en charge cette fonctionnalité, mais beaucoup le font maintenant. Le proxy TCP ne peut pas voir le contenu HTTP transféré en texte clair, mais cela n'affecte pas sa capacité à transférer les paquets dans les deux sens. De cette manière, le client et le serveur peuvent communiquer entre eux à l'aide du proxy. C'est le moyen sécurisé de proxy des données HTTPS.

Il existe également une manière non sécurisée de le faire, dans laquelle le proxy HTTP devient un homme du milieu. Il reçoit la connexion initiée par le client, puis initie une autre connexion au serveur réel. Dans un SSL / TLS bien implémenté, le client sera informé que le proxy n'est pas le vrai serveur. Le client doit donc faire confiance au proxy en ignorant l'avertissement pour que les choses fonctionnent. Après cela, le proxy décrypte simplement les données d'une connexion, les rechiffre et les alimente dans l'autre.

Enfin, nous pouvons certainement proxy HTTPS via un proxy SOCKS , car le proxy SOCKS fonctionne à un niveau inférieur. Vous pouvez penser qu'un proxy SOCKS est à la fois un proxy TCP et un proxy UDP.

Cyker
la source
L'utilisation de CONNECT entraînerait-elle des avertissements de sécurité comme mentionné dans stackoverflow.com/a/3118759/632951 ?
Pacerier
@Pacerier Je ne pense pas. En mode CONNECT, le proxy fonctionne au niveau de la couche de transport.
Cyker
Ainsi, par la méthode CONNECT, les données https du client ne sont pas transmises au niveau application du proxy intermédiaire? Et juste évalué au niveau TCP du proxy et relayé directement vers le serveur distant ?
zzinny
15

autant que je me souvienne, vous devez utiliser une requête HTTP CONNECT sur le proxy. cela convertira la connexion de demande en un tunnel TCP / IP transparent.

vous devez donc savoir si le serveur proxy que vous utilisez prend en charge ce protocole.

chburd
la source
3
En effet, les clients utilisent le verbe CONNECT pour utiliser les URI https: // via des serveurs proxy HTTP. Dans ce cas, la connexion est tunnellisée via le proxy, de sorte que la vérification du certificat est effectuée comme d'habitude, comme si le client parlait directement au serveur final.
Bruno
1
@chburd, mais les proxys prennent-ils généralement en charge HTTP CONNECT?
Pacerier
9

Si cela vous intéresse encore, voici une réponse à une question similaire: Convertir le proxy HTTP en proxy HTTPS dans Twisted

Pour répondre à la deuxième partie de la question:

Si oui, quel type de serveur proxy permet cela?

Hors de la boîte, la plupart des serveurs proxy seront configurés pour autoriser les connexions HTTPS uniquement au port 443, de sorte que les URI https avec des ports personnalisés ne fonctionneraient pas. Ceci est généralement configurable, en fonction du serveur proxy. Squid et TinyProxy prennent en charge cela, par exemple.

Bruno
la source
5

Voici mon code Java complet qui prend en charge les requêtes HTTP et HTTPS à l'aide du proxy SOCKS.

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);
        }
    }
}
âme machine
la source
3

Vous pouvez accomplir cela en utilisant des techniques man-in-the-middle avec la génération SSL dynamique. Jetez un œil à mitmproxy - c'est un proxy MITM basé sur Python et compatible SSL.

Zorayr
la source
3

tunneling HTTPS via SSH (version 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

tout ce que vous faites sur localhost. puis:

target_domain.com is accessible from localhost browser.
Sławomir Lenart
la source
1

J'avais essayé

  • commencer le tunneling: ssh -N -D 12345 login@proxy_server
  • Définir le proxy dans les paramètres de Firefox comme localhost:12345
    • et en cochant "utiliser ce proxy pour tous les protocoles"

mais cela entraînait l'erreur «Connexion non sécurisée» chaque fois que j'essayais de me connecter à un site Web https.

La solution était de

  • "décochez" le "utiliser ce proxy pour tous les protocoles"
  • définir le proxy "localhost: 12345" uniquement en tant que proxy SOCKS
  • et laissez le proxy HTTP, le proxy SSL, le proxy FTP vide

Référence tirée de la documentation numérique sur l'océan

Comment acheminer le trafic Web en toute sécurité sans VPN à l'aide d'un tunnel SOCKS

shadi
la source
1

Je ne pense pas que "avoir des connexions HTTPS sur des serveurs proxy" signifie le type d'attaque Man-in-the-Middle du serveur proxy. Je pense que cela demande si l'on peut se connecter à un serveur proxy http via TLS. Et la réponse est oui.


Est-il possible d'avoir des connexions HTTPS sur des serveurs proxy?

Oui, voir ma question et ma réponse ici. Le serveur proxy HTTP ne fonctionne que dans SwitchOmega

Si oui, quel type de serveur proxy permet cela?

Le type de serveur proxy déploie des certificats SSL, comme le font les sites Web ordinaires. Mais vous avez besoin d'un pacfichier pour le navigateur pour configurer la connexion proxy via SSL.

Meule
la source