Απαντήσεις SOCKS5 στο .NET 7+: χειρισμός μερικών αναγνώσεων TCP
Διάβασε το σταθερό πρόθεμα της απάντησης εντολής SOCKS5 και το επίθημα που εξαρτάται από το ATYP χωρίς να βασίζεσαι στα όρια εγγραφής TCP του διακομιστή.
Ένας διακομιστής SOCKS5 γράφει τέσσερα byte ξεχωριστά και ο πελάτης λειτουργεί μόνο αφού αυτές οι εγγραφές συνδυαστούν. Ο συνδυασμός μπορεί να αλλάξει τον χρονισμό, αλλά το TCP εξακολουθεί να μην υπόσχεται μία ανάγνωση ανά εγγραφή.
Ο πελάτης χρειάζεται έναν αναλυτή απάντησης. Μετά την επιλογή μεθόδου και τυχόν απαιτούμενη πιστοποίηση, μια απάντηση εντολής SOCKS5 αρχίζει με τέσσερα byte: έκδοση, αποτέλεσμα, εφεδρικό byte και τύπο διεύθυνσης. Το υπόλοιπο μήκος εξαρτάται από αυτόν τον τύπο διεύθυνσης.
Ένας αναλυτής .NET 7+ που χρειάζεται να καταναλώσει μόνο μια επιτυχή απάντηση CONNECT μπορεί να χρησιμοποιήσει:
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);
}
Τα δύο τελευταία byte είναι η δεσμευμένη θύρα. Το IPv4 χρειάζεται τέσσερα byte· το IPv6 χρειάζεται δεκαέξι· μια διεύθυνση τομέα φέρει ένα byte μήκους πριν από το όνομα.
Παρέχει ένα διακριτικό ακύρωσης με την προβλεπόμενη προθεσμία διαπραγμάτευσης. Το ReadExactlyAsync χειρίζεται μικρότερες μεμονωμένες αναγνώσεις και πετά εξαίρεση όταν η ροή τελειώσει πριν από το ζητούμενο μήκος. Σε αποτυχία, απόρριψε την αποτυχημένη σύνδεση μέσω της διαδρομής καθαρισμού του ιδιοκτήτη της.
Σε επιτυχία, σταμάτα στο όριο της απάντησης. Τα byte μετά από αυτό ανήκουν στο πρωτόκολλο προορισμού. Μια μεγαλύτερη κερδοσκοπική ανάγνωση πρέπει να διατηρεί τα πλεονάζοντα byte αντί να πετά την αρχή της ροής εφαρμογής.