2009-07-16 3 views
0

Ich bin relativ neu in Socket-Programmierung, so dass dies wie eine sehr lahme Frage klingen mag. Ich muss authentifiziertes TCP (MD5 als eine TCP-Option zu Beginn) als Transport für eine Anwendung verwenden. Ich habe mich gefragt, ob dies mit der Sockets-API geschehen könnte oder ob es eine andere Form einer existierenden TCP-API gibt, mit der ich das gleiche machen könnte. Ich würde mich freuen, wenn ich dabei helfen könnte.Gibt es eine Möglichkeit, TCP-Optionen mithilfe der Sockets-API festzulegen?

Antwort

1

Ich bin ein bisschen verwirrt durch Ihre Frage. Sie können mit der setsockopt Funktion Socket-Optionen auf einem Socket setzen, aber durch den Klang des Rests Ihrer Frage ist das nicht ganz das, was Sie meinen. Ich habe noch nie von einem Transportprotokoll namens Authentifiziertes TCP gehört und google wirft nichts nützliches. Ist es ein Standard? Gibt es einen RFC?

Wenn Sie nur eine sichere, authentifizierte TCP-Transportschicht zu wollen, dann sollten Sie in schauen Sockets Layer Secure oder SSL kurz oder dessen Ersatz, Transport Layer Security oder TLS kurz. Es wird mit ziemlicher Sicherheit eine Implementierung für jede Sprache geben, die Sie verwenden (Sie haben dies nicht angegeben).

ist auch, was meinst du mit MD5 für die Authentifizierung? MD5 ist ein Hashalgorithmus, jedoch nicht kollisionsresistent genug für die Kommunikation, die sichere Signaturen erfordert.

Bearbeiten aha! Sie sprechen über TCP-Optionen, verstehe ich jetzt. Ich habe keine Implementierungen dieser speziellen TCP-Option gesehen, die in einer der Socket-APIs integriert ist, so dass Sie hier möglicherweise kein Glück haben. Es hängt von der Implementierung ab, die Sie verwenden, aber es kann besonders selten sein, da es sich um eine ziemlich obskure TCP-Option handelt, die das Border Gateway-Protokoll verbessert, nicht etwas, das Sie normalerweise außerhalb von Routing-Software verwenden würden. Für den Fall, es unterstützt wird, können Sie so etwas wie dies gesetzt, es würde:

BOOL optVal = TRUE; 
int optLen = sizeof(BOOL); 

if (setsockopt(
     socket, 
     IPPROTO_TCP, 
     TCP_WHATEVER, 
     optVal, 
     optLen) != SOCKET_ERROR) { 
    printf("Success\n"); 
} 
+0

Danke IRBMe! Ich beziehe mich auf RFC 2385. Um eine lange Geschichte kurz und auf der Grundlage der Art der Anwendung, müssen wir TCP mit MD5-Option als Transport (C-Implementierung) verwenden. Ich sehe Sockets API als eine mögliche Option, um diese Art von Transport einzurichten. Ich habe mich gefragt, ob es einen anderen API-Satz gibt, der dasselbe tun könnte, aber gleichzeitig die Implementierung ein wenig vereinfacht. danke! –

0

Wenn Sie für die TCP-MD5 Option beschrieben durch RFC 2385, einige Systeme wie FreeBSD unterstützen eine boolean TCP_MD5SIG Option suchen, dies zu ermöglichen. Es ist auf einem Sockel wie folgt aktiviert:

int opt = 1; 
setsockopt(sockfd, IPPROTO_TCP, TCP_MD5SIG, &opt, sizeof(opt)); 

tcp(4) für weitere Details.

Linux hat eine andere Version von diesem, die einen struct-Parameter verwendet; Die anderen Antworten hier haben einige zusätzliche Details.

+0

Nun, das ist falsch. 'opt' ist kein int in dieser Sockopt. Es ist struct tcpm_addr. – user31986

+0

@ user31986: oh danke, auf FreeBSD ist es eine boolesche Option, aber anscheinend verwendet es eine Struktur unter Linux. Ich habe die Antwort aktualisiert, um dies zu verdeutlichen. – mark4o

+0

Diese Option kann auf keiner Plattform boolesch sein, da Sie auch einen Schlüssel angeben sollten. –

0

Ich habe gerade eine TCP-MD5-Verbindungsklasse in Ruby implementiert und dachte, dass dieses Code-Snippet jemand anderen die Mühe sparen könnte (zumindest jeder, der es unter Linux tut, wo die Einrichtung nicht dokumentiert ist). Das war nur von Kopfzeilen und Experimentieren; hoffentlich ist der Ruby für Leute, die in anderen Sprachen schreiben, nicht zu gruselig.

class TCPMD5Socket < Socket 
    IPPROTO_TCP = 6 # linux/in.h 
    TCP_MD5SIG = 14 # linux/tcp.h 
    TCP_MD5SIG_MAXKEYLEN = 80 # linux/tcp.h 

    # Works exactly the same as TCPSocket.open except you can supply a password 
    # to pass to the kernel for MD5 authhentication. 
    # 
    def initialize(host, port, password) 
    raise ArgumentError.new("Password is too long") if 
     password.length > TCP_MD5SIG_MAXKEYLEN 

    family = Socket.const_get(IPAddr.new(host).ipv4? ? "AF_INET" : "AF_INET6") 
    super(family, Socket::SOCK_STREAM, 0)  
    # struct tcp_md5sig { 
    # struct __kernel_sockaddr_storage tcpm_addr; /* address associated */ 
    # __u16 __tcpm_pad1;    /* zero */ 
    # __u16 tcpm_keylen;    /* key length */ 
    # __u32 __tcpm_pad2;    /* zero */ 
    # __u8 tcpm_key[TCP_MD5SIG_MAXKEYLEN];  /* key (binary) */ 
    # }; 
    tcp_md5sig_buffer = [ 
     Socket.pack_sockaddr_in(port, host), 0, password.length, 0, password 
    ].pack("a128SSLa#{TCP_MD5SIG_MAXKEYLEN}")  
    setsockopt(IPPROTO_TCP, TCP_MD5SIG, tcp_md5sig_buffer) 
    connect(Socket.pack_sockaddr_in(port, host)) 
    end 
end 

Dies wird nicht, aber Linux 2.6.20 an auf etwas arbeiten, aber zumindest, wenn Sie stattdessen auf FreeBSD sind, ist es in einem man page beschrieben.Hier

1

ist die Nutzung für Linux: http://criticalindirection.com/2015/05/12/tcp_md5sig/

sockopt Struktur:

struct tcp_md5sig { 
    struct __kernel_sockaddr_storage tcpm_addr; 
    __u16 __tcpm_pad1; 
    __u16 tcpm_keylen; 
    __u32 __tcpm_pad2; 
    __u8 tcpm_key[TCP_MD5SIG_MAXKEYLEN]; 
}; 

Die Linux-man-Seite hat keinen Hinweis, obwohl die Funktionalität im Kernel und libc vorhanden ist.

Aus dem Link:

Die Socket-Option TCP_MD5SIG speichert eine Abbildung der Pre-Shared-MD5-Schlüssel gegen den entsprechenden Peer-Endpunkt. Es ist zwingend erforderlich, den Client an eine bestimmte IP und einen bestimmten Port zu binden, die dem Server bekannt sind. Die Setsockopt() muss auf dem Listenet-Socket des Servers und dem Verbindungssocket des Clients aufgerufen werden, bevor die Verbindung() von Client aufgerufen wird.

Es hat auch volle Client-Server-Beispiel. Unten ist ein Schnipsel:

//Sockets Layer Call: bind() 
memset((char *) &cl_addr, 0, sizeof(cl_addr)); 
cl_addr.sin6_family = AF_INET6; 
if(inet_pton(AF_INET6, c6ip, &cl_addr.sin6_addr) <= 0) 
    error("ERROR on inet_pton"); 
cl_addr.sin6_port = htons(atoi(cport)); 

if (bind(sockfd, (struct sockaddr *) &cl_addr, sizeof(cl_addr)) < 0) 
    error("ERROR on binding"); 


memset((char *) &serv_addr, 0, sizeof(serv_addr)); 
serv_addr.sin6_family = AF_INET6; 
if(inet_pton(AF_INET6, s6ip, &serv_addr.sin6_addr) <= 0) 
    error("ERROR on inet_pton"); 
serv_addr.sin6_port = htons(atoi(sport)); 


memcpy(&md5.tcpm_addr, &serv_addr, sizeof(serv_addr)); 
strcpy(md5.tcpm_key, key); 
md5.tcpm_keylen = strlen(key); 

if ((r = setsockopt(sockfd, IPPROTO_TCP, TCP_MD5SIG, &md5, sizeof(md5))) < 0) 
    error("listen setsockopt TCP_MD5SIG"); 
Verwandte Themen