Сначала задайте приоритет правил и безопасное поведение при ошибках. Ниже действует первое совпадение, по умолчанию доступ запрещён; любой некорректный элемент делает весь набор недействительным.
Брандмауэр с проверкой IP‑адресов
Сначала задайте приоритет правил и безопасное поведение при ошибках. Ниже действует первое совпадение, по умолчанию доступ запрещён; любой некорректный элемент делает весь набор недействительным.
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
Условие
Необходимо реализовать программу, имитирующую работу брандмауэра. Программа должна принимать набор правил, где каждое правило состоит из CIDR‑блока и действия ("ALLOW" или "DENY"). Основная функция должна проверять, разрешён ли заданный IP‑адрес согласно этим правилам, возвращая true для разрешённых и false для запрещённых. Также требуется корректно обрабатывать некорректные CIDR‑блоки и неизвестные действия.
package main
import (
"fmt"
)
// Функция проверки разрешения IP-адреса
func IsAllowed(rules [][2]string, ip string) bool {
// **Вставьте код проверки IP-адреса по правилам**
return false
}
func main() {
// **Пример входных данных:**
// **Пример 1:**
rules1 := [][2]string{
{"192.168.1.0/24", "ALLOW"},
{"10.0.0.0/16", "DENY"},
{"8.8.8.8", "ALLOW"},
}
ip1 := "192.168.1.10" // ответ true
// **Пример 2:**
rules2 := [][2]string{
{"192.168.1.0/24", "ALLOW"},
{"10.0.0.0/16", "DENY"},
{"8.8.8.8", "ALLOW"},
}
ip2 := "10.0.0.10" // ответ false
// **Пример 3:**
rules3 := [][2]string{
{"192.168.1.0/24", "ALLOW"},
{"10.0.0.0/16", "DENY"},
{"8.8.8.8", "ALLOW"},
}
ip3 := "192.168.2.10" // ответ false
processExample(rules1, ip1)
processExample(rules2, ip2)
processExample(rules3, ip3)
}
func processExample(rules [][2]string, ip string) {
if IsAllowed(rules, ip) {
fmt.Println("true")
} else {
fmt.Println("false")
}
}
Ответ
Сначала задайте приоритет правил и безопасное поведение при ошибках. Ниже действует первое совпадение, по умолчанию доступ запрещён; любой некорректный элемент делает весь набор недействительным.
Пример принимает и CIDR, и одиночные IP из условия. Нужен импорт net/netip:
func IsAllowed(rules [][2]string, ip string) bool {
addr, err := netip.ParseAddr(ip)
if err != nil || addr.Zone() != "" { return false }
addr = addr.Unmap()
type rule struct { prefix netip.Prefix; allow bool }
parsed := make([]rule, 0, len(rules))
for _, r := range rules {
if r[1] != "ALLOW" && r[1] != "DENY" { return false }
prefix, err := netip.ParsePrefix(r[0])
if err != nil {
host, e := netip.ParseAddr(r[0])
if e != nil || host.Zone() != "" { return false }
host = host.Unmap()
prefix = netip.PrefixFrom(host, host.BitLen())
} else if prefix.Addr().Is4In6() {
if prefix.Bits() < 96 { return false }
prefix = netip.PrefixFrom(prefix.Addr().Unmap(), prefix.Bits()-96)
}
parsed = append(parsed, rule{prefix.Masked(), r[1] == "ALLOW"})
}
for _, r := range parsed {
if r.prefix.Contains(addr) { return r.allow }
}
return false
}
Проверка всех правил до поиска исключает игнорирование ошибки после раннего ALLOW. IPv4-mapped IPv6 нормализуется; слишком широкий mapped-префикс отвергается. Для трёх примеров результат true, false, false. Bool-интерфейс не сообщает причину ошибки; для реального сервиса конфигурацию лучше валидировать один раз с возвратом error.
Источник: pkg.go.dev.