Геолокація IPv4 після передачі: як виправити країну
Коротка відповідь: після трансферу геолокація IPv4 може й далі показувати хибну країну (попередню), бо запис у реєстрі, анонс BGP і кожна комерційна GeoIP-база - окремі системи. Зміна в реєстрі не переписує бази. Працює таке: опублікувати власний файл розташування (geofeed за RFC 8805), послатися на нього в об'єкті RIPE Database і надіслати виправлення кожному провайдеру, зберігши номери тікетів. Жоден провайдер не гарантує дати. Перевірено 2026-10-14. Кроки на боці реєстру описано в нашому посібнику з трансферу RIPE NCC; цей матеріал починається, коли блок уже ваш.
Чотири записи - чотири різні питання
| Запис | Відповідає на | Хто задає | На що може впливати |
|---|---|---|---|
| Запис RIR (WHOIS) | Хто тримає блок | Власник, у реєстрі | Ідентифікація власника. country: не є місцем розташування |
| Origin у BGP і ROA | Хто анонсує і чи це дозволено | Ви, на своїх маршрутизаторах і в RPKI | Досяжність і валідність маршруту, а не країна |
| Geofeed (RFC 8805) | Де, за словами оператора, використовується префікс | Ви, у файлі на вашому хостингу | Підказка для провайдерів, які його читають |
| Комерційна GeoIP-база | Де, на думку вендора, перебуває адреса | Вендор, зі своїх джерел | Що бачать сайти й застосунки |
П'яте - де сервери насправді - це те, що решта чотирьох намагаються змоделювати. Документація RIPE Database каже, що ніколи не визначалося, що означає country:, тому його не можна надійно використовувати для зіставлення IP-адрес із країнами, а RIPE NCC заявляє, що не є геолокаційним провайдером. Блок може бути зареєстрований на компанію в одній країні, а працювати в іншій, і обидва записи будуть правильними.
Діагностика: один чек-лист і один скрипт
| Перевірка | Команда | На що впливає |
|---|---|---|
| CIDR і запис у реєстрі | whois -h whois.ripe.net -r -T inetnum 192.0.2.0/24 |
Власник, country:, рядок geofeed: |
| Файл geofeed | curl -s <url з geofeed:> |
Підказка розташування для провайдерів, що його читають |
| Origin AS і ROA | RIPEstat prefix-overview, rpki-validation |
Маршрутизація й валідність маршруту, а не країна |
| Записи провайдерів | Публічна сторінка пошуку провайдера | Країна, яку бачать ваші користувачі й партнери |
| Зворотний DNS | dig -x 192.0.2.1 |
Перевірки пошти й читабельність логів; жодне з перевірених джерел не бере з нього країну |
192.0.2.0/24, 198.51.100.0/24, 203.0.113.0/24 та 2001:db8::/32 - документаційні префікси: використовуйте їх лише для синтаксису, бо вони не анонсуються, а запит до RIPE повертає для них батьківський блок поза RIPE. Для живого виводу ми беремо власний префікс DCXV і AS204057 (запущено 2026-10-14; Linux, whois 5.6, jq 1.8; у системі без файлу services додайте -p 43 до whois):
$ whois -h whois.ripe.net -r -T inetnum 178.23.189.0/24 | grep -E '^(inetnum|netname|country|geofeed)'
inetnum: 178.23.189.0 - 178.23.189.255
netname: CY-DCXV-20210903
country: CY
geofeed: https://dcxv.com/geofeed.csv
$ curl -s 'https://stat.ripe.net/data/prefix-overview/data.json?resource=178.23.189.0/24' | jq -c '.data.asns'
[{"asn":204057,"holder":"DCXV-AS DCXV INTERNATIONAL LTD"}]
$ curl -s 'https://stat.ripe.net/data/rpki-validation/data.json?resource=204057&prefix=178.23.189.0/24' | jq -r '.data.status'
valid
Реєстр каже CY, бо власник - кіпрська компанія, а сервери деінде. Origin AS і ROA валідні, атрибут geofeed: присутній. Таке поєднання нормальне, і саме тому провайдер може показати країну, якої реєстр не вказує. DCXV публікує дані своєї мережі тут. Якщо у вас блок із такою проблемою, можете звернутися до нас щодо трансферу IPv4.
Скрипт нижче (Python 3.8+, лише стандартна бібліотека, перевірено на 3.14, тільки ресурси регіону RIPE) друкує об'єкт реєстру, origin AS, статус RPKI і найспецифічніший рядок geofeed для префікса через RIPE Database та RIPEstat. Ми запускали його на префіксах DCXV, на документаційних префіксах і на помилкових сценаріях. Зіставлення з фідом перевірено й офлайн на зразковому файлі.
#!/usr/bin/env python3
"""geocheck.py PREFIX - registry country, origin ASN, RPKI status and geofeed line for a prefix.
Python 3.8+, standard library only. Data: RIPE Database REST API and RIPEstat (RIPE region only)."""
import csv, io, ipaddress, json, sys, time, urllib.error, urllib.parse, urllib.request
def get(url):
req = urllib.request.Request(url, headers={'Accept': 'application/json', 'User-Agent': 'geocheck/1.0'})
for attempt in range(4):
try:
with urllib.request.urlopen(req, timeout=20) as r:
return r.read(5_000_000).decode('utf-8-sig', 'replace') # cap the read at 5 MB
except OSError as e: # includes HTTP 429 and connection resets
if isinstance(e, urllib.error.HTTPError) and 400 <= e.code < 500 and e.code != 429:
sys.exit('request refused for %s: %s' % (url, e)) # retrying a 4xx will not help
if attempt == 3:
sys.exit('network error for %s: %s' % (url, e))
time.sleep(2 ** attempt)
def stat(call, **q):
return json.loads(get('https://stat.ripe.net/data/%s/data.json?%s' % (call, urllib.parse.urlencode(q))))['data']
def registry(net):
# best match: the most specific inetnum / inet6num that covers the prefix
t = 'inet6num' if net.version == 6 else 'inetnum'
q = urllib.parse.urlencode([('query-string', str(net)), ('source', 'ripe'), ('type-filter', t),
('flags', 'no-referenced'), ('flags', 'no-irt')])
try:
obj = json.loads(get('https://rest.db.ripe.net/search.json?' + q))['objects']['object'][0]
except (ValueError, KeyError, IndexError):
return None
return {a['name']: a['value'] for a in obj['attributes']['attribute']}
def feed_match(url, net):
# most specific feed entry that covers the prefix; RFC 8805 columns: prefix,country,region,city
best = None
for row in csv.reader(io.StringIO(get(url))):
if not row or row[0].lstrip().startswith('#'):
continue
try:
p = ipaddress.ip_network(row[0].strip(), strict=False)
except ValueError:
continue
if p.version == net.version and net.subnet_of(p) and (best is None or p.prefixlen > best[0].prefixlen):
best = (p, row)
return best[1] if best else None
def main(arg):
try:
net = ipaddress.ip_network(arg, strict=False)
except ValueError:
sys.exit('usage: geocheck.py PREFIX (for example 192.0.2.0/24)')
if net.prefixlen == net.max_prefixlen:
sys.exit('give the prefix, not a single address: a /32 or /128 gives a misleading RPKI result')
if net.prefixlen == 0:
sys.exit('give a real prefix, not the default route')
print('prefix ', net)
reg = registry(net)
top = reg and ((reg.get('netname') or '').startswith('NON-RIPE-NCC-MANAGED')
or (reg.get('inetnum') or '').startswith('0.0.0.0 -') or reg.get('inet6num') == '::/0')
if not reg or top:
print('registry object outside the RIPE NCC: query that RIR instead')
else:
print('registry object ', reg.get('inetnum') or reg.get('inet6num'), '| netname', reg.get('netname'), '| status', reg.get('status'))
print('registry country ', reg.get('country'), '(country: is not a location)')
ov = stat('prefix-overview', resource=str(net))
asns = [str(a['asn']) for a in ov.get('asns', [])]
print('origin ASN ', ', '.join('AS' + a for a in asns) or 'not announced (no origin in RIPEstat)')
for a in asns:
print('RPKI AS%-9s' % a, stat('rpki-validation', resource=a, prefix=str(net))['status'])
url = None if top else (reg or {}).get('geofeed')
if not url:
print('geofeed none (no geofeed: attribute on the best-match object)')
return
print('geofeed URL ', url)
if not url.startswith('https://'):
sys.exit('geofeed URL is not https://, not fetched')
row = feed_match(url, net)
print('geofeed line ', ','.join(row[:4]) if row else 'NO entry covers this prefix')
if __name__ == '__main__':
if len(sys.argv) != 2:
sys.exit('usage: geocheck.py PREFIX')
main(sys.argv[1])
Потрібні valid і рядок фіда для вашого префікса. "NO entry covers this prefix" означає, що провайдери, які читають ваш фід, пропустять блок.
Куди надсилати виправлення
Користуйтеся актуальним каналом кожного провайдера; виправлення в одного не виправляє решту. Документацію перевірено 2026-10-14.
| Провайдер | Канал | Що сказано в документації |
|---|---|---|
| MaxMind | Разові форми; GeoIP Exchange для операторів | Приймає geofeed за RFC 8805 і RFC 9632, розгляд раз на робочий день; дати релізу немає |
| IPinfo | Сторінка виправлень; geofeed | Допис у спільноті (2026-02-05): спершу вимірювання, geofeed вибірково |
| DB-IP | Посилання report у результаті; пакетно через форму контакту | Зміна запису WHOIS від RIR зазвичай запускає оновлення; geofeed - ще один шлях |
| IP2Location | Контакт і звіт про точність даних | Дати релізів за ліцензіями; публічної процедури виправлень чи geofeed не знайдено |
| Форма IP report у Search Help | Оновлення можуть тривати понад місяць ("may take more than a month"); індивідуальної відповіді немає |
Опублікуйте geofeed і зв'яжіть його з об'єктом
Geofeed - це CSV-файл за RFC 8805: ip_prefix,alpha2code,region,city. Вкладені префікси дозволені, перемагає найспецифічніший. RFC вимагає UTF-8 і розриви рядків CRLF, оголошує поштовий індекс застарілим (тож пропустіть його) і дозволяє споживачам вважати дані лише підказкою. Мінімальний файл із документаційними префіксами:
# prefix,country,region,city
192.0.2.0/24,CZ,CZ-10,Prague
2001:db8::/32,CZ,CZ-10,Prague
Розмістіть файл на HTTPS і додайте один рядок geofeed: https://example.net/geofeed.csv до свого inetnum чи inet6num; атрибут необов'язковий і єдиний. RFC 9632 велить споживачам брати найспецифічніший об'єкт із geofeed і ігнорувати інші підказки, зокрема country:. Він також визначає необов'язковий підпис RPKI для файлу; які провайдери його перевіряють, ми не перевіряли. Після трансферу прочитайте об'єкт: рядок geofeed:, залишений продавцем, вказує на файл, який вам не підконтрольний.
План дій для нового власника
- Зберіть докази. Запис у реєстрі, де ви власник, список CIDR і підтвердження, де працюють сервери.
- Виправте свою частину. Поправте рядок
geofeed:, опублікуйте файл, запустіть скрипт. - Подайте кожному провайдеру. По одному запиту з URL фіда. Вказуйте лише справжнє розташування: провайдери можуть звіряти його зі своїми вимірюваннями.
- Ведіть журнал. Номер тікета, дата, провайдер, префікс, відповідь.
- Перевірте пізніше. Дати ніхто не обіцяє, тож не прив'язуйте запуск до неї.
Симптом, причина, перевірка, дія
| Симптом | Імовірна причина | Перевірка | Дія |
|---|---|---|---|
| Кілька провайдерів показують попередню країну | Немає geofeed або його ще не прочитано | Скрипт: є рядок geofeed: і відповідний запис? |
Опублікувати фід, потім по виправленню кожному провайдеру |
| Один провайдер іде за реєстром, а не за фідом | Провайдер не використовує фіди | Його документація й пошук | Надіслати виправлення з URL фіда |
| Фід доступний, а старі дані лишаються | Затримка релізу, збій завантаження або вимірювання не збігаються | HTTPS доступний, префікс покрито, немає конфліктного вкладеного запису | Запитати провайдера, зберегти тікет, перевірити пізніше |
| Помиляється лише один CDN, банк чи платіжний сервіс | Він має власні дані: Cloudflare, наприклад, оновлює базу кілька разів на тиждень і не може гарантувати збіг з іншими провайдерами; антифрод може зважати й на інші сигнали | Запитати, яке джерело він бере | Виправити це джерело, потім повідомити сервіс |
| Країна правильна, місто хибне | У фіді немає міста або вимірювання інші | Стовпець city у фіді | Додати region і city, потім запитати знову |

Оцініть ризик до купівлі
Чорні списки й зловживання - у чек-листі due diligence; тут лише геолокація. Перевірте префікс у кількох провайдерів зараз, прочитайте його inetnum (country: і будь-який URL geofeed:) та з'ясуйте, хто контролює цей файл. Домовтеся в договорі, що продавець передасть або прибере посилання на фід під час закриття.
Наступний крок
Не певні, де розрив? Звернутися щодо трансферу IPv4 або напишіть на ipv4@dcxv.com, вказавши префікс і симптом. Ми не обіцяємо, коли провайдер оновить дані.
