Comments 27
Еще бы найти красивое решение, что бы туннель не засыпал время от времени. А то пока приходится скриптом раз в пол часа туннель тушить/поднимать. Работает, но костыль страшный =)
если ipsec транспортный (а не туннельный), то можно во вложенном туннеле использовать keep alive
В Netwatch клиента ставите пинг любого хоста из подсети VPN-сервера (или внутренний адрес самого сервера), тогда туннель никогда не заснет. Но, как сказали выше, гораздо проще использовать IPsec в транспортном режиме.
Лично мой неполный список «хотелок» к роутерос включает в себя:
Всё это дело потихоньку сподвигает меня расковырять прошивку и допилить отсутствующее собственноручно, но пока тупо некогда.
- Открытые спеки на модули
- IPSEC как интерфейс
- LLDP
- Вменяемое управление vlan
- Переменные в правилах, туда же — dns-менеджер, как в Asterisk.
- Группы интерфейсов (как вариант — переменная типа «массив» для использования в правилах фв)
- Группы MAC-адресов
- Триггеры на события, с лихим перепиливанием всей ныне кривой системы Scripting, размазанной по scheduler, netwatch и system scripts
- Железку за $150, тянущую 100 мбит ipsec.
Всё это дело потихоньку сподвигает меня расковырять прошивку и допилить отсутствующее собственноручно, но пока тупо некогда.
А ещё очень сильно хочется создавать динамические объекты из скрипта. Перезагрузил роутер, или остановил скрипт — они хопа, и исчезли.
Допустим, скрипт по хттпс (с аутентификацией сертификатом, естественно) получает список next hop-ов, создаёт динамические правила фв, пиры и политики ipsec, загоняет сети в ospf, получает маршруты — и хопа, уже NHRP не нужен, всё вполне себе опенсорсненько, реализуемо в виде скрипта на баше под другие платформы и у циски чутка жим-жим за мелкобизнес.
Эх, я б к ним работать пошел, да климат в Латвии не очень =(
Допустим, скрипт по хттпс (с аутентификацией сертификатом, естественно) получает список next hop-ов, создаёт динамические правила фв, пиры и политики ipsec, загоняет сети в ospf, получает маршруты — и хопа, уже NHRP не нужен, всё вполне себе опенсорсненько, реализуемо в виде скрипта на баше под другие платформы и у циски чутка жим-жим за мелкобизнес.
Эх, я б к ним работать пошел, да климат в Латвии не очень =(
Управление Vlan'ами в последней версии на crs (может на других моделях тоже, не проверил ещё) вполне ок стало =) раньше был лютый костыль, а про железку, имхо, не реально за 150$ получить чип с аппаратной поддержкой шифрования.
Ну вот у Убиков получилось же 111 мегабит за $90
www.just.ru/router_internet/294607_marshrytizator_ubiquiti_erlite_3_eu_marshrytizator
blog.linitx.com/ubiquiti-edgerouter-performance-testing/
www.just.ru/router_internet/294607_marshrytizator_ubiquiti_erlite_3_eu_marshrytizator
blog.linitx.com/ubiquiti-edgerouter-performance-testing/
Напишите фичреквест у них в вики, может запилят когда-нибудь. Вообще же эти ребята пока вполне окучивают свою нишу, и собственно даже их решения с 10G — это тот же пионернет, по сути. Просто сейчас даже пионеры уже потихоньку дорастают до 10G.
А вообще, список претензий к ним длинный. Причем даже во вполне тривиальных вещах
А вообще, список претензий к ним длинный. Причем даже во вполне тривиальных вещах
- IPSEC как интерфейс
Используйте транспортный режим, вложенный туннель (GRE/IPIP/L2TP) и будет желаемым интерфейсом.
- Группы интерфейсов (как вариант — переменная типа «массив» для использования в правилах фв)
Сам уже давно жду эту функцию, будет очень полезна.
Эх, научилось бы оно наконец OpenVPN по UDP :)
Openvpn хорош, чертяка. Но ipsec таки лучше, хотя бы распространенностью своей.
Но если очень нужно прям openvpn (была у меня одна точка — из вариантов доступа был только хттп-прокси, а людям нужен был внутренний впн) — пошаманьте с Метароутером, у меня с какой-то древней версией Openwrt openvpn вполне пристойно бегал, мегабит 20 снимал с железки на mipsbe.
Но если очень нужно прям openvpn (была у меня одна точка — из вариантов доступа был только хттп-прокси, а людям нужен был внутренний впн) — пошаманьте с Метароутером, у меня с какой-то древней версией Openwrt openvpn вполне пристойно бегал, мегабит 20 снимал с железки на mipsbe.
Хорош, но микротик на него откровенно забил, и развивать больше не собирается, насколько я знаю.
Может не все так плохо.
What's new in 6.28rc13 (2015-Mar-13 16:06):
*) made metarouter work on boards with 802.11ac support or usb LTE;
What's new in 6.28rc13 (2015-Mar-13 16:06):
*) made metarouter work on boards with 802.11ac support or usb LTE;
Я не про metarouter скорее, а по openvpn =)
пишите пост в фич реквест лист чем больше авторов тем выше шансы.
Немного поправил скрипт, что бы так же менялся sa-src-address при смене внешнего ip
:if ([:len [/system script job find script=SetIpSecDstAddrFromDns]]>1) do={
:error
}
:local DnsNameFromComment
:local ResolvedIpFromComment
:local ResolvedIpWithMaskFromComment
:local IpDstAddr
:local IpSaSrcAddr
:local IpSaDstAddr
:local IpPublic
:foreach IpSecPolicyCount in=[/ip ipsec policy find] do={
:set DnsNameFromComment [/ip ipsec policy get $IpSecPolicyCount comment]
:if ($DnsNameFromComment!="") do={
:do {
:set ResolvedIpFromComment ([:resolve $DnsNameFromComment])
:set ResolvedIpWithMaskFromComment ($ResolvedIpFromComment. "/32")
:set IpDstAddr [/ip ipsec policy get $IpSecPolicyCount dst-address]
:set IpSaSrcAddr [/ip ipsec policy get $IpSecPolicyCount sa-src-address]
:set IpSaDstAddr [/ip ipsec policy get $IpSecPolicyCount sa-dst-address]
:set IpPublic [ /ip cloud get public-address]
:if ($ResolvedIpWithMaskFromComment!=$IpDstAddr or $ResolvedIpFromComment!=$IpSaDstAddr) do={
:log warning («Public ip router » .$IpPublic)
:log warning ("[SetIpSecSrcAddrFromDns] Change IpSec policy src-addr from ". $IpSaSrcAddr. " — to-- ". $IpPublic)
:log warning ("[SetIpSecDstAddrFromDns] Change IpSec policy dst-addr from ". $IpSaDstAddr. " — to-- ". $ResolvedIpFromComment)
/ip ipsec policy set $IpSecPolicyCount sa-src-address=$IpPublic sa-dst-address=$ResolvedIpFromComment
}
} on-error={
:set ResolvedIpFromComment «unknown»
:log error ("[SetIpSecDstAddrFromDns] Cant resolve name ". $DnsNameFromComment)
}
}
}
:local IpPeerAddr
:foreach IpSecPeerCount in=[/ip ipsec peer find] do={
:set DnsNameFromComment [/ip ipsec peer get $IpSecPeerCount comment]
:if ($DnsNameFromComment!="") do={
:do {
:set ResolvedIpFromComment [:resolve $DnsNameFromComment]
:set ResolvedIpWithMaskFromComment ($ResolvedIpFromComment. "/32")
:set IpPeerAddr [/ip ipsec peer get $IpSecPeerCount address]
:if ($ResolvedIpWithMaskFromComment!=$IpPeerAddr) do={
:log warning ("[SetIpSecDstAddrFromDns] Change IpSec peer addr from ". $IpPeerAddr. " to ". $ResolvedIpFromComment)
/ip ipsec peer set $IpSecPeerCount address=$ResolvedIpWithMaskFromComment
}
} on-error={
:set ResolvedIpFromComment «unknown»
:log error ("[SetIpSecDstAddrFromDns] Cant resolve name ". $DnsNameFromComment)
}
}
}
:local IpPeerAddr
:foreach IpSecPeerCount in=[/ip ipsec peer find] do={
:set DnsNameFromComment [/ip ipsec peer get $IpSecPeerCount comment]
:if ($DnsNameFromComment!="") do={
:do {
:set ResolvedIpFromComment [:resolve $DnsNameFromComment]
:set ResolvedIpWithMaskFromComment ($ResolvedIpFromComment. "/32")
:set IpPeerAddr [/ip ipsec peer get $IpSecPeerCount address]
:if ($ResolvedIpWithMaskFromComment!=$IpPeerAddr) do={
:log warning ("[SetIpSecDstAddrFromDns] Change IpSec peer addr from ". $IpPeerAddr. " to ". $ResolvedIpFromComment)
/ip ipsec peer set $IpSecPeerCount address=$ResolvedIpWithMaskFromComment
}
} on-error={
:set ResolvedIpFromComment «unknown»
:log error ("[SetIpSecDstAddrFromDns] Cant resolve name ". $DnsNameFromComment)
}
}
}
автору респект
:if ([:len [/system script job find script=SetIpSecDstAddrFromDns]]>1) do={
:error
}
:local DnsNameFromComment
:local ResolvedIpFromComment
:local ResolvedIpWithMaskFromComment
:local IpDstAddr
:local IpSaSrcAddr
:local IpSaDstAddr
:local IpPublic
:foreach IpSecPolicyCount in=[/ip ipsec policy find] do={
:set DnsNameFromComment [/ip ipsec policy get $IpSecPolicyCount comment]
:if ($DnsNameFromComment!="") do={
:do {
:set ResolvedIpFromComment ([:resolve $DnsNameFromComment])
:set ResolvedIpWithMaskFromComment ($ResolvedIpFromComment. "/32")
:set IpDstAddr [/ip ipsec policy get $IpSecPolicyCount dst-address]
:set IpSaSrcAddr [/ip ipsec policy get $IpSecPolicyCount sa-src-address]
:set IpSaDstAddr [/ip ipsec policy get $IpSecPolicyCount sa-dst-address]
:set IpPublic [ /ip cloud get public-address]
:if ($ResolvedIpWithMaskFromComment!=$IpDstAddr or $ResolvedIpFromComment!=$IpSaDstAddr) do={
:log warning («Public ip router » .$IpPublic)
:log warning ("[SetIpSecSrcAddrFromDns] Change IpSec policy src-addr from ". $IpSaSrcAddr. " — to-- ". $IpPublic)
:log warning ("[SetIpSecDstAddrFromDns] Change IpSec policy dst-addr from ". $IpSaDstAddr. " — to-- ". $ResolvedIpFromComment)
/ip ipsec policy set $IpSecPolicyCount sa-src-address=$IpPublic sa-dst-address=$ResolvedIpFromComment
}
} on-error={
:set ResolvedIpFromComment «unknown»
:log error ("[SetIpSecDstAddrFromDns] Cant resolve name ". $DnsNameFromComment)
}
}
}
:local IpPeerAddr
:foreach IpSecPeerCount in=[/ip ipsec peer find] do={
:set DnsNameFromComment [/ip ipsec peer get $IpSecPeerCount comment]
:if ($DnsNameFromComment!="") do={
:do {
:set ResolvedIpFromComment [:resolve $DnsNameFromComment]
:set ResolvedIpWithMaskFromComment ($ResolvedIpFromComment. "/32")
:set IpPeerAddr [/ip ipsec peer get $IpSecPeerCount address]
:if ($ResolvedIpWithMaskFromComment!=$IpPeerAddr) do={
:log warning ("[SetIpSecDstAddrFromDns] Change IpSec peer addr from ". $IpPeerAddr. " to ". $ResolvedIpFromComment)
/ip ipsec peer set $IpSecPeerCount address=$ResolvedIpWithMaskFromComment
}
} on-error={
:set ResolvedIpFromComment «unknown»
:log error ("[SetIpSecDstAddrFromDns] Cant resolve name ". $DnsNameFromComment)
}
}
}
:local IpPeerAddr
:foreach IpSecPeerCount in=[/ip ipsec peer find] do={
:set DnsNameFromComment [/ip ipsec peer get $IpSecPeerCount comment]
:if ($DnsNameFromComment!="") do={
:do {
:set ResolvedIpFromComment [:resolve $DnsNameFromComment]
:set ResolvedIpWithMaskFromComment ($ResolvedIpFromComment. "/32")
:set IpPeerAddr [/ip ipsec peer get $IpSecPeerCount address]
:if ($ResolvedIpWithMaskFromComment!=$IpPeerAddr) do={
:log warning ("[SetIpSecDstAddrFromDns] Change IpSec peer addr from ". $IpPeerAddr. " to ". $ResolvedIpFromComment)
/ip ipsec peer set $IpSecPeerCount address=$ResolvedIpWithMaskFromComment
}
} on-error={
:set ResolvedIpFromComment «unknown»
:log error ("[SetIpSecDstAddrFromDns] Cant resolve name ". $DnsNameFromComment)
}
}
}
автору респект
Пара замечаний:
- Условие проверки (if) на смену IpSaSrcAddr необходимо скорректировать, а именно надо сравнивать IpSaSrcAddr и IpPublic
- Данная корректировка будет верна только для роутеров с внешним адресом. Если ваш роутер находится за NAT, то в IpSaSrcAddr необходимо подставлять не внешний IP, а IP интерфейса, который идет к шлюзу. Я другим скриптом проверяю внешний IP роутера и адрес, который указан в маршруте по умолчанию, сравниваю их, если они не равны, делаю вывод, что роутер находится за NAT. Если тебя будет интересно, распишу подробнее.
Спасибо большое за статью и предложенный скрипт.
Поскольку активно пользуюсь туннельным режимом IPsec, внес небольшое изменение в скрипт, чтобы он не изменял dst-addr, для соответствующих правил.
Поскольку активно пользуюсь туннельным режимом IPsec, внес небольшое изменение в скрипт, чтобы он не изменял dst-addr, для соответствующих правил.
:if ([:len [/system script job find script=SetIpSecDstAddrFromDns]]>1) do={ :error } :local DnsNameFromComment :local ResolvedIpFromComment :local ResolvedIpWithMaskFromComment :local IpDstAddr :local IpSaDstAddr :local TunnelPolicy :foreach IpSecPolicyCount in=[/ip ipsec policy find] do={ :set DnsNameFromComment [/ip ipsec policy get $IpSecPolicyCount comment] :if ($DnsNameFromComment!="") do={ :do { :set ResolvedIpFromComment ([:resolve $DnsNameFromComment]) :set ResolvedIpWithMaskFromComment ($ResolvedIpFromComment . "/32") :set IpDstAddr [/ip ipsec policy get $IpSecPolicyCount dst-address] :set IpSaDstAddr [/ip ipsec policy get $IpSecPolicyCount sa-dst-address] :set TunnelPolicy [/ip ipsec policy get $IpSecPolicyCount tunnel] :if ($ResolvedIpWithMaskFromComment!=$IpDstAddr or $ResolvedIpFromComment!=$IpSaDstAddr) do={ :if ($TunnelPolicy=no) do={ :log warning ("[SetIpSecDstAddrFromDns] Change IPsec policy dst-addr and sa-dst-addr from " . $IpSaDstAddr . " to " . $ResolvedIpFromComment . " for $DnsNameFromComment") /ip ipsec policy set $IpSecPolicyCount dst-address=$ResolvedIpWithMaskFromComment sa-dst-address=$ResolvedIpFromComment } else={ :log warning ("[SetIpSecDstAddrFromDns] Change IPsec tunnel policy dst-addr from " . $IpSaDstAddr . " to " . $ResolvedIpFromComment . " for $DnsNameFromComment") /ip ipsec policy set $IpSecPolicyCount sa-dst-address=$ResolvedIpFromComment } } } on-error={ :set ResolvedIpFromComment "unknown" :log error ("[SetIpSecDstAddrFromDns] Cant resolve name " . $DnsNameFromComment) } } } :local IpPeerAddr :foreach IpSecPeerCount in=[/ip ipsec peer find] do={ :set DnsNameFromComment [/ip ipsec peer get $IpSecPeerCount comment] :if ($DnsNameFromComment!="") do={ :do { :set ResolvedIpFromComment [:resolve $DnsNameFromComment] :set ResolvedIpWithMaskFromComment ($ResolvedIpFromComment . "/32") :set IpPeerAddr [/ip ipsec peer get $IpSecPeerCount address] :if ($ResolvedIpWithMaskFromComment!=$IpPeerAddr) do={ :log warning ("[SetIpSecDstAddrFromDns] Change IPsec peer addr from " . $IpPeerAddr . " to " . $ResolvedIpFromComment . " for $DnsNameFromComment") /ip ipsec peer set $IpSecPeerCount address=$ResolvedIpWithMaskFromComment } } on-error={ :set ResolvedIpFromComment "unknown" :log error ("[SetIpSecDstAddrFromDns] Cant resolve name " . $DnsNameFromComment) } } }
Спасибо за статью! Однако в последней версии прошивки что-то не работает. Вижу, что не те адреса заменяет скрипт. Вы могли бы глянуть, т.к. в программировании Mikrotik не силен. P.S. Вижу исправления :-)
Друзья, вожно выложить актуальный работающий скрипт, который будет проверять и менять как Destination Address, так и Source Address? Большое спасибо.
Sign up to leave a comment.
Mikrotik: настройка IPsec на автоматическое обновление адреса VPN сервера