Без обид, но ответ об использовании bind () совершенно неправильный. bind () будет управлять исходным IP-адресом, помещенным в заголовок IP-пакета. Он не управляет тем, какой интерфейс будет использоваться для отправки пакета: с помощью таблицы маршрутизации ядра будет определено, какой интерфейс имеет наименьшую стоимость для достижения определенного места назначения. (* см. примечание)
Вместо этого вы должны использовать SO_BINDTODEVICE
sockopt. Это делает две вещи:
- Пакеты всегда будут выходить из указанного вами интерфейса, независимо от того, что говорят таблицы маршрутизации ядра.
- В сокет будут передаваться только пакеты, поступающие на указанный интерфейс. Пакеты, поступающие на другие интерфейсы, не будут.
Если у вас есть несколько интерфейсов, между которыми вы хотите переключиться, я бы предложил создать один сокет на интерфейс. Поскольку вы также будете получать пакеты только на интерфейс, к которому привязаны, вам нужно будет добавить все эти сокеты в select()
/ poll()
/ независимо от того, что вы используете.
#include <net/if.h>
struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, "eth1", sizeof(ifr.ifr_name));
if (setsockopt(s, SOL_SOCKET, SO_BINDTODEVICE,
(void *)&ifr, sizeof(ifr)) < 0) {
perror("SO_BINDTODEVICE failed");
}
(* примечание)
Bind()
IP-адрес интерфейса может привести к запутанному, но, тем не менее, правильному поведению. Например, если вы bind()
на IP-адрес для eth1, но таблица маршрутизации отправляет пакет eth0, тогда пакет появится на проводе eth0, но с IP-адресом источника интерфейса eth1. Это странно, но разрешено, хотя пакеты, отправленные обратно на IP-адрес eth1, будут перенаправлены обратно на eth1. Вы можете проверить это, используя систему Linux с двумя интерфейсами iP. У меня есть один, и я проверил его, и bind()
не эффективен для управления пакетом физического интерфейса.
Хотя это технически разрешено, но в зависимости от топологии это может не сработать. Чтобы подавить распределенные атаки типа «отказ в обслуживании», когда злоумышленники используют поддельные IP-адреса источника, многие маршрутизаторы теперь выполняют проверки переадресации обратного пути (RPF). Пакеты с IP-адресом источника по «неправильному» пути могут быть отброшены.