Согласование ip-адреса с таблицей масок подсети... Каков наилучший подход в Java?
Вот сценарий... У меня есть таблица подсетей. (см. ниже) У меня есть IP-адрес. Я хотел бы узнать, в какой подсети находится ip-адрес, на основе поиска в таблице. Затем эта ассоциация будет использоваться для определения того, в каком месте находится пользователь. Это частное сетевое пространство, поэтому стандартный поиск по местоположению в Интернете не будет применяться. Какой был бы лучший подход? Нужно ли мне разбить ip-адрес на его числовые части и поразрядное сравнение со всеми подсетями.. или есть встроенные инструменты в Java API, которые могли бы облегчить мою жизнь для сравнения IP-адреса с маской подсети?
Я в основном ищу лучший способ сравнить ipaddress с заданной маской подсети и определить да, это совпадение, или нет. Это необязательно. Будут также оценены любые советы о том, как сохранить список и выполнить поиск с минимальными операциями.
В идеале я бы делал что-то похожее на это:
List subnetInfo = null;
subnetInfo = findSubnet('192.168.0.1'); //value null if nothing found
....
//return null if nothing found
List findSubnet(String ipaddress) {
List subnetDetails = null;
.... code here ...
return subnetDetails;
}
Таблица 1: Пример списка подсетей
dk-ballerup-gen-off-v411 10.172.80.0/21 NANR-denmark-ballerup-metallbuen66-ground-first-floors-incl-dhcp-(sr14585203)
ae-dubai-ofssl-gen-off-v410 10.172.88.0/24 NANR-arab-emirates-ofssl-iflex-general-office-v410-(sr12781477)
ru-stpetersburg-gen-off-v411 10.172.89.0/24 NANR-russia-stpetersburg-general-office-incl-dhcp (bsteinba)
Ответы
Ответ 1
Apache Commons Net имеет SubnetUtils для такого рода вещей, включая определение того, находится ли данный IP-адрес в данной подсети.
Тривиальный пример:
String[] subnetsMasks = { ... };
Collection<SubnetInfo> subnets = new ArrayList<SubnetInfo>();
for (String subnetMask : subnetsMasks) {
subnets.add(new SubnetUtils(subnetMask).getInfo());
}
String ipAddress = ...;
for (SubnetInfo subnet : subnets) {
if (subnet.isInRange(ipAddress)) {
System.out.println("IP Address " + ipAddress + " is in range " + subnet.getCidrSignature());
}
}
Ответ 2
Помните, что этот IP-адрес представляет собой только значение int
для исторических причин, представленных в виде четырех октетов в десятичной форме.
Для того же токена, подсеть действительно представляет собой диапазон последовательных ints
от сетевого адреса до широковещательного адреса.
Поэтому, если ваш объект IP-адреса имеет конвертер int, вы можете просто проверить, находится ли это целое число в пределах подсети, выполнив простые сравнения int.
Ответ 3
Если ваша таблица является таблицей SQL И ваша база данных - PostgreSql, вы можете использовать PostgreSQL types и functions.
Хорошо, что много условий...
Ответ 4
Поверните IP-адрес и сетевую маску в int и AND вместе. Если результат равен IP-адресу, это адрес в этой сетевой маске. Обратите внимание, что вы можете получить более одного соответствия, если ваши сетевые маски не отличаются.
Ответ 5
Это старый вопрос, но я подумал, что стоит спасти кого-то еще от боли, которая причинила мне.
Удалите класс Apache Commons Net SubnetUtils, он не работает:
http://en.newinstance.it/2009/03/25/checking-if-an-ip-is-in-a-subnet-range-subnetutilssubnetinfo-isinrange-bug/
Ответ 6
Я столкнулся с тем же вопросом, что и вы, но ограничился частными сетями (192.168.X.X, 10.x.x.x, ...
и IPv6).
Если вы тоже ограничены этим случаем, вы должны использовать встроенный InetAddress.isSiteLocalAddress()
Ответ 7
Я построил на вершине решения скаффмана один метод. Для тех, кто интересуется решением для копирования пасты:
/**
* Checks if client ip equals or is in range of ip networks provided by
* semicolon separated list
*
* @param clientIp in numeric form like "192.168.0.10"
* @param ipList like "127.0.0.1;192.168.0.0/24;10.0.0.0/8"
* @return true if client ip from the list os ips and networks
*/
protected boolean evaluateIp(String clientIp, String ipList) {
BusinessLogger log = getLog();
log.debug("Evaluate ip ");
if (ipList == null) {
log.info("No ip address provided in ApiPrivilege");
return false;
}
String[] subnetMasks = ipList.split(";");
for (String subnetMask : subnetMasks) {
subnetMask = subnetMask.trim();
if (eq(subnetMask, clientIp))
return true;
if (subnetMask.contains("/")) {
if (new SubnetUtils(subnetMask).getInfo().isInRange(clientIp))
return true;
}
}
return false;
}