Простая изоляция клиентов ЛВС с *nix роутером
Порой приходится изолировать пользователей друг от друга, разрешив доступ только к определенным портам (причин может быть множество: запрет сетевых игр, ограничение распространения червей и т.п.), либо — вообще зарубить обмен между некоторыми клиентскими машинами на корню, оставив только доступ к серверу либо интернету.
Типичное в этом случае решение — vlan per user, однако оно, не смотря на свою очевидность, имеет и минусы, главный из которых — при росте кол-ва пользователей соответственно растет и кол-во вланов, а при наличии цепочки из нескольких свичей без поддержки SNMP (как, к примеру, бюджетная TPLink websmart серия, которая вполне применима для пользования на средних размеров предприятии, либо — даже у ISP) поднимать вланы становится утомительным. + не совсем рациональное использование адресного пространства (актуально, если абонентам выдаются белые адреса). Альтернативное решение — пользовать port-based vlan, но при этом становится невозможным обмен между клиентами, либо — придется опять-таки поднимать на каждого клиента свою подсеть, что есть не совсем удобно и не совсем рационально использует адресное пространство.
Идеальным решением было бы использование некоего подобия ip unnumbered в сочетании с port-based vlan (либо — даже без оного, если пользователи назначить адреса в ручную не смогут). И это, как показали эксперименты, вполне возможно. Суть решения — выдача клиентам IP адресов с маской /32. Да-да, шлюз будет при этом находиться в другой подсети — подсеть клиента-то ограничена одним его адресом. Но, тем не менее, это работает. Как работает (и какие дополнительные условия) — расскажу чуть ниже, с учетом особенностей 2-х классов ОС, с правильно реализованной сетевой подсистемой (читать *nix), и с неправильно реализованной сетевой подсистемой (читать Windows).
Итак, начнем с Windows. В ней, как это ни странно звучит, попытка назначить шлюз из абсолютно другой подсети, к которой система не знает маршрута, не вызывает никакого сопротивления — маршрут к шлюзу назначается через интерфейс, на котором этот шлюз прописан. Т.е. — выдаем клиенту 192.168.0.5/32 со шлюзом 192.168.0.254, и все работает. Один минус — вручную назначить маску подсети /32 не выйдет, как бы вы не бились. Ни как основной IP, ни как дополнительный. Впрочем, никто не помешает назначить допустим 192.168.0.5/30, и шлюз 192.168.0.254 — все опять-таки будет прекрасно работать. Хотя и не должно, если следовать логике.
Теперь же — перейдем к самому интересному: *nix системам. На попытку назначить дефолтный маршрут через шлюз, к которому нет маршрута — правильная ОС пошлет куда подальше, даже если указать интерфейс, через который вроде как должны ходить пакеты. Что вполне логично. Однако, решение есть: перед тем, как добавить дефолтный маршрут, остаточно всего лишь добавить маршрут к дефолтному шлюзу через интерфейс (ip route add 192.168.0.254/32 dev eth0). А при выдаче через DHCP — достаточно выдать classless или classful маршрут к шлюзу через 0.0.0.0 (шлюз 0.0.0.0 — подразумевает, что IP адрес назначения находится в этом же сегменте и, соответственно, обращение к нему идет напрямую).
Осталось одно: конфигурация собственно роутера. На нем поднимается подсеть нужной ширины (в данном примере — назначается адрес 192.168.0.254/24), как будто все клиенты работают с обычной /24 подсетью, и естественно DHCP сервер.
Итого, для работы всех клиентов (ну, возможно, кроме особо кривых китайских SOHO роутеров), достаточно поднять на роутере DHCP, указать в конфиге выдавать клиентам подсеть /32, и выдавать дополнительно маршрут на дефолтный шлюз через 0.0.0.0. Вот пример конфига DHCP сервера моей тестовой подсети:
subnet 192.168.0.0 netmask 255.255.255.0 {
range 192.168.0.1 192.168.0.253;
option static-routes 192.168.0.254 0.0.0.0;
option routers 192.168.0.254;
option domain-name-servers 192.168.0.254;
option subnet-mask 255.255.255.255;
}
Эксперименты показали стабильную работу как с Windows (XP, 7), так и с Linux (различные дистрибутивы, в т.ч. embedded linux SOHO роутеров). Полномасштабных экспериментов с сотнями устройств/операционок не ставил, но из того что было под руками — несовместимости не обнаружил.
Типичное в этом случае решение — vlan per user, однако оно, не смотря на свою очевидность, имеет и минусы, главный из которых — при росте кол-ва пользователей соответственно растет и кол-во вланов, а при наличии цепочки из нескольких свичей без поддержки SNMP (как, к примеру, бюджетная TPLink websmart серия, которая вполне применима для пользования на средних размеров предприятии, либо — даже у ISP) поднимать вланы становится утомительным. + не совсем рациональное использование адресного пространства (актуально, если абонентам выдаются белые адреса). Альтернативное решение — пользовать port-based vlan, но при этом становится невозможным обмен между клиентами, либо — придется опять-таки поднимать на каждого клиента свою подсеть, что есть не совсем удобно и не совсем рационально использует адресное пространство.
Идеальным решением было бы использование некоего подобия ip unnumbered в сочетании с port-based vlan (либо — даже без оного, если пользователи назначить адреса в ручную не смогут). И это, как показали эксперименты, вполне возможно. Суть решения — выдача клиентам IP адресов с маской /32. Да-да, шлюз будет при этом находиться в другой подсети — подсеть клиента-то ограничена одним его адресом. Но, тем не менее, это работает. Как работает (и какие дополнительные условия) — расскажу чуть ниже, с учетом особенностей 2-х классов ОС, с правильно реализованной сетевой подсистемой (читать *nix), и с неправильно реализованной сетевой подсистемой (читать Windows).
Итак, начнем с Windows. В ней, как это ни странно звучит, попытка назначить шлюз из абсолютно другой подсети, к которой система не знает маршрута, не вызывает никакого сопротивления — маршрут к шлюзу назначается через интерфейс, на котором этот шлюз прописан. Т.е. — выдаем клиенту 192.168.0.5/32 со шлюзом 192.168.0.254, и все работает. Один минус — вручную назначить маску подсети /32 не выйдет, как бы вы не бились. Ни как основной IP, ни как дополнительный. Впрочем, никто не помешает назначить допустим 192.168.0.5/30, и шлюз 192.168.0.254 — все опять-таки будет прекрасно работать. Хотя и не должно, если следовать логике.
Теперь же — перейдем к самому интересному: *nix системам. На попытку назначить дефолтный маршрут через шлюз, к которому нет маршрута — правильная ОС пошлет куда подальше, даже если указать интерфейс, через который вроде как должны ходить пакеты. Что вполне логично. Однако, решение есть: перед тем, как добавить дефолтный маршрут, остаточно всего лишь добавить маршрут к дефолтному шлюзу через интерфейс (ip route add 192.168.0.254/32 dev eth0). А при выдаче через DHCP — достаточно выдать classless или classful маршрут к шлюзу через 0.0.0.0 (шлюз 0.0.0.0 — подразумевает, что IP адрес назначения находится в этом же сегменте и, соответственно, обращение к нему идет напрямую).
Осталось одно: конфигурация собственно роутера. На нем поднимается подсеть нужной ширины (в данном примере — назначается адрес 192.168.0.254/24), как будто все клиенты работают с обычной /24 подсетью, и естественно DHCP сервер.
Итого, для работы всех клиентов (ну, возможно, кроме особо кривых китайских SOHO роутеров), достаточно поднять на роутере DHCP, указать в конфиге выдавать клиентам подсеть /32, и выдавать дополнительно маршрут на дефолтный шлюз через 0.0.0.0. Вот пример конфига DHCP сервера моей тестовой подсети:
subnet 192.168.0.0 netmask 255.255.255.0 {
range 192.168.0.1 192.168.0.253;
option static-routes 192.168.0.254 0.0.0.0;
option routers 192.168.0.254;
option domain-name-servers 192.168.0.254;
option subnet-mask 255.255.255.255;
}
Эксперименты показали стабильную работу как с Windows (XP, 7), так и с Linux (различные дистрибутивы, в т.ч. embedded linux SOHO роутеров). Полномасштабных экспериментов с сотнями устройств/операционок не ставил, но из того что было под руками — несовместимости не обнаружил.
0 комментариев