2016-10-14 6 views
-1

Я использую геолокации таблицы Maxmind (в частности, вплоть до города/уровень страны), один из этих таблиц имеет такую ​​структуру:Как я могу сопоставить автономный IP-адрес с CIDR?

enter image description here

Я хранить IP-адреса пользователей моей службы в другой таблице; Я создал столбцы latitude и longitude и хочу сохранить соответствующую широту и долготу этих IP-адресов в таблице пользователей (в соответствующей строке для IP-адреса).

Как видно, IP-адреса в таблице MaxMind хранятся в формате CIDR, что означает, что невозможно проверить, подходит ли IP-адрес в диапазоне IP, заданном CIDR.

Возможно ли соответствовать регулярному IP-протоколу CIDR, используя только инструкцию MySQL?

Я попытался это, но тем не менее нашел следующее:

  • Это является возможно, но мне нужна маска подсети (я не имею)
  • I может получить подсеть маска из сырого IP, однако это требует CIDR ...

в соответствие с IP-адреса в таблице users в CIDR нотации в таблице MaxMind займет некоторое время, я нно га программы стандарта C# CLI для обработки партии, и я признаю, что я могу это сделать:

  1. Получить на всю Maxmind таблицы в устройстве для чтения данных
  2. Go, хотя каждый ряд и преобразовать CIDR в диапазон IP-
  3. в то же время, открыть чтения данных в таблице users и сопоставить данный IP в диапазоне IP
  4. UPDATE соответствующая запись в users с широты и долготы, что соответствует CIDR от ранее

Как вы можете видеть, мой метод кажется мне неэффективным и может занять гораздо больше времени, чем нужно.

Могу ли я сопоставить обычный IP-адрес с CIDR просто с помощью оператора MySQL? Если нет, могу ли я рассчитать диапазон IP без маску подсети и затем соответствовать IP?

Столбцы, которые имеют отношение в users таблице следующим образом:

enter image description here

+0

«Могу ли я сопоставить обычный IP-адрес с CIDR просто с помощью оператора MySQL?» Нет. «Можно ли рассчитать диапазон IP без маски подсети, а затем соответствовать IP?» Нет. Как вы могли узнать диапазон без маски подсети? – itsme86

+0

Один из подходов - добавить столбец. CIDR - это всего лишь небольшая маска сетевой части адреса, поэтому для каждого диапазона у вас есть столбец с только частью сети (как целое число.) Затем вы можете взять IP-адрес, который вы ищете, начать в конце и начните делать участок сети короче и короче, пока не получите совпадение или не закончите бит. Это будет <23 запросов. Грубая сила и уродливость. Можете ли вы сделать это с помощью MySQL? Я был бы удивлен. – Duston

+0

@ itsme86 Я пытаюсь найти способ хранения широты и долготы для IP-адресов в таблице 'users' с тем, что у меня есть, без использования платной услуги геолокации. – cybermonkey

ответ

0

Если это поможет, я написал этот класс некоторое время назад для проверки, если IP-адрес находится в пределах диапазона. Вам просто нужно разделить сеть и маску в строке CIDR, проанализировать их и передать в конструктор. Затем вы можете просто использовать ContainsIP(), чтобы узнать, попадает ли этот IP-адрес в эту сеть. Вероятно, он может использовать другой конструктор, который принимает строку CIDR для обработки разделения/синтаксического анализа.

public class IPNetwork 
{ 
    private readonly IPAddress _networkMask; 
    private readonly int _networkMaskLength; 
    private readonly uint _networkMaskValue; 

    public IPNetwork(IPAddress networkMask, int networkMaskLength) 
    { 
     if (networkMask.AddressFamily != AddressFamily.InterNetwork) 
      throw new InvalidOperationException("Only IPv4 networks are supported."); 

     _networkMask = networkMask; 
     _networkMaskLength = networkMaskLength; 
     _networkMaskValue = GetMaskedAddress(networkMask); 
    } 

    public bool ContainsIP(IPAddress ipAddress) 
    { 
     return GetMaskedAddress(ipAddress) == _networkMaskValue; 
    } 

    private uint GetMaskedAddress(IPAddress ipAddress) 
    { 
     byte[] bytes = ipAddress.GetAddressBytes(); 
     int addressLength = bytes.Length * 8; 
     uint addressValue = BytesToValue(bytes); 

     uint maskedAddress = 0; 
     for (int i = addressLength - _networkMaskLength; i < addressLength; ++i) 
      maskedAddress |= addressValue & (1U << i); 

     return maskedAddress; 
    } 

    private uint BytesToValue(byte[] bytes) 
    { 
     uint value = 0; 

     for (int i = 0; i < bytes.Length; ++i) 
      value |= (uint)(bytes[bytes.Length - i - 1] << (i * 8)); 

     return value; 
    } 
}