Un serveur SOCKS5 écrit quatre octets séparément, et le client ne fonctionne qu'une fois ces écritures combinées. Les combiner peut modifier le timing, mais TCP ne promet toujours pas une lecture par écriture.

Le client a besoin d'un analyseur de réponse. Après la sélection de la méthode et toute authentification requise, une réponse de commande SOCKS5 commence par quatre octets : version, résultat, octet réservé et type d'adresse. La longueur restante dépend de ce type d'adresse.

Un analyseur .NET 7+ qui n'a besoin de consommer qu'une réponse CONNECT réussie peut utiliser :

static async Task ReadConnectReply(Stream stream, CancellationToken ct)
{
    byte[] prefix = new byte[4];
    await stream.ReadExactlyAsync(prefix, ct);
    if (prefix[0] != 5 || prefix[2] != 0)
        throw new IOException("Invalid SOCKS5 reply");
    if (prefix[1] != 0)
        throw new IOException($"SOCKS5 request failed: {prefix[1]}");

    int remaining;
    switch (prefix[3])
    {
        case 1: remaining = 4 + 2; break;
        case 4: remaining = 16 + 2; break;
        case 3:
            byte[] length = new byte[1];
            await stream.ReadExactlyAsync(length, ct);
            remaining = length[0] + 2;
            break;
        default:
            throw new IOException("Unknown SOCKS5 address type");
    }
    await stream.ReadExactlyAsync(new byte[remaining], ct);
}

Les deux derniers octets sont le port lié. IPv4 nécessite quatre octets ; IPv6 en nécessite seize ; une adresse de domaine porte un octet de longueur avant son nom.

Fournissez un jeton d'annulation avec l'échéance de négociation prévue. ReadExactlyAsync gère des lectures individuelles plus courtes et lève une exception lorsque le flux se termine avant la longueur demandée. En cas d'échec, écartez la connexion échouée via le chemin de nettoyage de son propriétaire.

En cas de succès, arrêtez-vous à la frontière de la réponse. Les octets qui suivent appartiennent au protocole de destination. Une lecture spéculative plus large doit conserver les octets excédentaires au lieu de jeter le début du flux applicatif.

Articles similaires