Есть ли способ установить параметры TCP с помощью API сокетов? - PullRequest
0 голосов
/ 16 июля 2009

Я относительно новичок в программировании сокетов, так что это может звучать как очень неубедительный вопрос. Я должен использовать аутентифицированный TCP (MD5 в качестве опции TCP для начала) в качестве транспорта для некоторых приложений. Мне было интересно, можно ли это сделать с помощью API сокетов или есть какая-то другая форма существующих API-интерфейсов TCP, которую я мог бы использовать для того же. Буду признателен, если смогу помочь с этим.

Ответы [ 4 ]

2 голосов
/ 16 мая 2015

Вот использование для Linux: http://criticalindirection.com/2015/05/12/tcp_md5sig/

структура sockopt:

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

Справочная страница Linux не имеет ссылки, хотя функциональность присутствует в ядре и libc.

Из ссылки:

Опция сокета TCP_MD5SIG сохраняет отображение предварительно общего ключа MD5 против соответствующей конечной точки. Обязательно связывать клиент с конкретным IP и портом, известным серверу. setsockopt () должен быть вызван на слушающем сокете сервера и сокет подключения клиента, перед тем как вызывается connect () клиент.

Также имеется полный пример клиент-сервер. Ниже приведен фрагмент:

//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");
1 голос
/ 16 июля 2009

Я немного смущен вашим вопросом. Конечно, вы можете установить параметры сокета для сокета, используя функцию setsockopt , но, судя по всему остальному вопросу, это не совсем то, что вы имеете в виду. Я никогда не слышал ни о каком транспортном протоколе под названием Аутентифицированный TCP , и Google не выдает ничего полезного. Это стандарт; есть ли RFC?

Если вы просто хотите получить защищенный аутентифицированный транспортный уровень TCP, то вам следует обратиться к Secure Sockets Layer, или SSL для краткости, или заменить его, Transport Layer Security или TLS для краткости. Почти наверняка будет реализация для любого языка, который вы используете (вы не указали).

Кроме того, что вы подразумеваете под MD5 для аутентификации? MD5 - это алгоритм хеширования, однако он недостаточно устойчив к коллизиям для использования в обмене данными, где требуются безопасные подписи.

Редактировать ага! Вы говорите о параметрах TCP, теперь я понимаю. Я не видел никаких реализаций этой конкретной опции TCP, встроенной в какой-либо из API сокетов, поэтому вам может не повезти здесь. Это зависит от используемой вами реализации, но это может быть особенно редко, учитывая, что это довольно непонятный вариант TCP, предназначенный для улучшения протокола пограничного шлюза, а не тот, который вы обычно используете для внешнего программного обеспечения маршрутизации. В случае, если это поддерживается, вы должны установить что-то вроде этого:

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

if (setsockopt(
      socket,
      IPPROTO_TCP,
      TCP_WHATEVER,
      optVal,
      optLen) != SOCKET_ERROR) {
    printf("Success\n");
}
0 голосов
/ 05 января 2011

Я только что реализовал класс соединения TCP-MD5 в Ruby и подумал, что этот фрагмент кода может спасти кого-либо еще (по крайней мере, любого, кто делает это в Linux, где средство не документировано). Это было просто смотреть на заголовки и экспериментировать; надеюсь, Ruby не слишком страшен для людей, пишущих на других языках.

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

Это не будет работать ни на чем, кроме Linux 2.6.20 и выше, но, по крайней мере, если вы вместо этого используете FreeBSD, это описано в man-странице .

0 голосов
/ 16 июля 2009

Если вы ищете опцию TCP-MD5, описанную RFC 2385 , некоторые системы, такие как FreeBSD, поддерживают логическую опцию TCP_MD5SIG, чтобы включить это. Он включается в сокет следующим образом:

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

Подробнее см. tcp(4).

В Linux есть другая версия, в которой используется параметр структуры; другие ответы здесь содержат некоторые дополнительные детали.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...