2017-12-17 8 views
0

Vielen Dank für das Lesen dieser Frage. Habe schon eine Weile an C-Sockeln gearbeitet - speziell an c thread-tcp-Buchsen mit tls. Verwenden der OpenSSL-API.C Threaded Sockets - tcp mit TLS, kann nicht IP/Ether Paket Header

Ich habe seit einiger Zeit ein Problem, wo ich die Quelle IP und Port bekommen kann - z. B. printf("Connection: %s:%d\n",inet_ntoa(d->addr.sin_addr), ntohs(d->addr.sin_port));.

Das Problem ist, dass ich alle Daten benötige - Ethernet und IP, wo ich Quell- und Ziel-IPs, MAC-Adressen, Protokoll, TTL ansehen kann und die Liste geht weiter.

Versuchte mehrere Beispiele aus dem Web wie dies von Binary Gezeiten

data_size = recvfrom(sock_raw , buffer , 65536 , 0 , &saddr , &saddr_size); 
unsigned short iphdrlen; 

struct iphdr *iph = (struct iphdr *)Buffer; 
iphdrlen =iph->ihl*4; 

memset(&source, 0, sizeof(source)); 
source.sin_addr.s_addr = iph->saddr; 

memset(&dest, 0, sizeof(dest)); 
dest.sin_addr.s_addr = iph->daddr; 
fprintf(logfile," |-Checksum : %d\n",ntohs(iph->check)); 
fprintf(logfile," |-Source IP  : %s\n",inet_ntoa(source.sin_addr)); 
fprintf(logfile," |-Destination IP : %s\n",inet_ntoa(dest.sin_addr)); 

Aber ich halte auf „Junk-Daten“ zu bekommen. Grundsätzlich sind die IPs und andere Felder seltsam und zufällig.

SSL_read() legt die Daten in einen Puffer (die HTTPS-Anfrage im Grunde), zu diesem Zeitpunkt bin ich schon zu spät? Ich habe versucht, den Socket vor dem Versuch SSL_Accept() zu lesen, also Lesen von einem unverschlüsselten Socket, bekomme ich immer noch die Junk-Daten.

Grundsätzlich kann jede Hilfe mit:

1) c Beispiele

2) brauche ich BIO zu benutzen?

3), was Prozess, den ich zu erfassen folgen, dass die Daten

in meinem Haupt ich nur Schleife zB

for (; ;) { 
    memset(&d->addr, 0, sizeof(d->addr)); 
    d->len = sizeof(d->addr); 
    if ((d->client = accept(d->server, (struct sockaddr*)&d->addr, &d->len)) > 0) { 
     pthread_create(&connection_thread, NULL, handleGuestConnection, (void *) d); 

hier ist ein Ausschnitt aus der Gewinde Funktion:

data *d = socketData; 

SSL *ssl; 
ssl = SSL_new(d->ctx); 
SSL_set_fd(ssl, d->client); 

int returnStatus = handleGuestSSLAccept(ssl); 

switch (returnStatus) { 
    case 1: { 
     break; 
     //Bad Socket 
    } 
    case 2: { 
     char *reply = HTTPHeaderResponse(2); 
     write(d->client, reply, strlen(reply)); 
     break; 
     //Redirect 
    } 
    case 3: { 
     char buf[1024] = {0}; 
     int bytes = SSL_read(ssl, buf, sizeof(buf)); 
     if (bytes > 0) { 
      buf[bytes] = '\0'; 
      char *reply = HTTPHeaderResponse(3); 
      SSL_write(ssl, reply, strlen(reply)); 
     } 
     break; 
     //Good 
    } 
} 
+0

Sie müssen verstehen, dass die Korrespondenz zwischen SSL-Daten und TCP-Paketen wird nicht 1 sein -bis 1. Es kann so ziemlich alles sein. Am besten nehmen Sie die Low-Level-Daten vollständig getrennt auf, z. B. mit einem Thread, der libpcap oder ähnliches verwendet. –

+0

Kann ich fragen, warum Sie die Low-Level-Details des Protokolls sehen wollen? Ist das nur eine Lernübung? Wenn ja, empfehle ich 'wireshark'.Für TLS haben die Kommandozeilen-Tools 'openssl s_client' und' s_server' eine schöne Debug-Option für das TLS-Messaging. Wenn Sie versuchen, Clients zu überprüfen, indem Sie die Protokolldetails überprüfen, gibt es vielleicht einen besseren Weg, um das zu erreichen, was Sie versuchen wollen ... – lockcmpxchg8b

+0

@DavidSchwartz - Ich habe das untersucht, kennen Sie irgendwelche Beispiele? Ich konnte nicht erfolgreich eine funktionierende Version – allThingsLinux

Antwort

0

In Dieser Code hier:

data_size = recvfrom(sock_raw , buffer , 65536 , 0 , &saddr , &saddr_size); 

die sock_raw ist ein Hinweis. Sie benötigen einen so genannten "Raw-Socket", der Ihnen Zugriff auf die zugrunde liegenden Pakete auf einer bestimmten Ebene gewährt (abhängig von Ihrer Plattform, die möglicherweise die Ethernet-Paket-Ebene oder nur IP enthält).

Referenzen: Linux, Windows.

+0

Ja, aber ist es möglich, openssl auf einen rohen Socket zu implementieren? Wenn ich versucht habe, meinen Socket 'socket zu ändern (AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0);' zu 'socket (AF_INET, SOCK_RAW, IPPROTO_TCP);' Ich bekomme eine Reihe von Fehlern bezüglich des Socket-Typs – allThingsLinux

+0

Ich habe es versucht wieder - Sie können es nicht einstellen, um auf einen bestimmten Port zu hören (oder zumindest kann ich nicht sehen, wie), so dass der Zweck besiegt würde. Irgendeine andere Idee? – allThingsLinux

+0

@allThingsLinux Sie versuchen, zwei völlig verschiedene Dinge zu kombinieren. Einer ist die TCP-Level-Verwendung der Verbindung. Der andere erhält die Rohdaten, die Sie möchten. Sie versuchen, den Code, der die erste Sache macht, in den Code umzuwandeln, der die zweite Sache tut, aber die zweite Sache erfordert völlig anderen Code. Holen Sie sich das erste Richtige, lassen Sie SSL arbeiten. Schreiben Sie dann einen separaten Code, um die gewünschten Rohdaten zu sammeln. –

-1

Für alle, die ein Proxy mit über eine integrierte Firewall zu erreichen - es ist nicht eine Aufgabe, Schritt 1-10 Programmierung ist. Sie können einen Proxy mit C/C++ erstellen oder Golang verwenden, wie ich es getan habe - gerne teilen, wenn Sie brauchen. In Bezug auf das Filtern von Paketen habe ich dies erreicht, indem ich ein Modul, das in C geschrieben wurde, in den Kernelraum unter Verwendung von insmod einfüge. Der Grund, warum Sie dies nicht von Ihrer Anwendung aus tun können, ist dies: Sobald ein Paket vom Kernel-Space an UserSpace übergeben wird, werden alle Header entfernt. Die einzige Möglichkeit, Header zu erfassen, besteht darin, ein Modul in den Kernel-Space einzufügen, der jedes Mal ausgelöst wird, wenn ein Paket ankommt. tcpdump.org hat ein paar guten Artikel, aber das wäre ihre Methoden verwenden, habe ich beschlossen, meine eigenen zu nutzen und ging mit einer Kernel-Modul