Geolokalizacja IPv4 po transferze: jak poprawić kraj
Krótka odpowiedź: po transferze geolokalizacja IPv4 może nadal pokazywać zły kraj (poprzedni), bo wpis w rejestrze, anons BGP i każda komercyjna baza GeoIP to osobne systemy. Zmiana w rejestrze nie przepisuje baz. Działa takie podejście: opublikować własny plik lokalizacji (geofeed wg RFC 8805), odwołać się do niego w obiekcie RIPE Database i wysłać poprawkę każdemu dostawcy, zachowując numery zgłoszeń. Żaden dostawca nie gwarantuje terminu. Sprawdzono 2026-10-14. Kroki po stronie rejestru opisuje nasz przewodnik po transferze RIPE NCC; ten tekst zaczyna się, gdy blok jest już Twój.
Cztery wpisy, cztery różne pytania
| Wpis | Odpowiada na | Kto go ustala | Na co może wpływać |
|---|---|---|---|
| Wpis RIR (WHOIS) | Kto jest posiadaczem bloku | Posiadacz, w rejestrze | Tożsamość posiadacza. country: nie jest lokalizacją |
| Origin BGP i ROA | Kto go anonsuje i czy ma to upoważnienie | Ty, na routerach i w RPKI | Osiągalność i ważność trasy, nie kraj |
| Geofeed (RFC 8805) | Gdzie według operatora używany jest każdy prefiks | Ty, w pliku, który hostujesz | Wskazówka dla dostawców, którzy go czytają |
| Komercyjna baza GeoIP | Gdzie dostawca uważa, że jest adres | Dostawca, z własnych źródeł | To, co widzą strony i aplikacje |
Piąty element, czyli miejsce, w którym naprawdę stoją Twoje serwery, to to, co pozostałe cztery próbują odwzorować. Dokumentacja RIPE Database mówi, że nigdy nie określono, co oznacza country:, więc nie można go niezawodnie używać do przypisywania adresów IP do krajów, a RIPE NCC oświadcza, że nie jest dostawcą geolokalizacji. Blok może być zarejestrowany na firmę w jednym kraju, a działać w innym, i oba wpisy są poprawne.
Diagnoza: jedna lista i jeden skrypt
| Sprawdzenie | Polecenie | Wpływa na |
|---|---|---|
| CIDR i wpis w rejestrze | whois -h whois.ripe.net -r -T inetnum 192.0.2.0/24 |
Posiadacza, country:, wiersz geofeed: |
| Plik geofeed | curl -s <URL z geofeed:> |
Wskazówkę lokalizacji dla dostawców, którzy go czytają |
| Origin AS i ROA | RIPEstat prefix-overview, rpki-validation |
Routing i ważność trasy, nie kraj |
| Dane dostawców | Publiczna wyszukiwarka dostawcy | Kraj widziany przez użytkowników i partnerów |
| Reverse DNS | dig -x 192.0.2.1 |
Kontrole poczty i czytelność logów; żadne sprawdzone źródło nie bierze z niego kraju |
192.0.2.0/24, 198.51.100.0/24, 203.0.113.0/24 i 2001:db8::/32 to prefiksy dokumentacyjne: używaj ich tylko do składni, bo nie są anonsowane, a zapytanie do RIPE zwraca dla nich nadrzędny blok spoza RIPE. Do wyniku na żywo używamy własnego prefiksu DCXV i AS204057 (uruchomiono 2026-10-14; Linux, whois 5.6, jq 1.8; w systemie bez pliku services dodaj -p 43 do 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
Rejestr mówi CY, bo posiadaczem jest cypryjska firma, a serwery stoją gdzie indziej. Origin AS i ROA są ważne, a atrybut geofeed: jest obecny. Takie połączenie jest normalne i dlatego dostawca może pokazać kraj, którego rejestr nie podaje. DCXV publikuje dane swojej sieci tutaj. Jeśli masz blok z takim problemem, możesz wysłać do nas zapytanie o transfer IPv4.
Poniższy skrypt (Python 3.8+, tylko biblioteka standardowa, przetestowany na 3.14, wyłącznie zasoby regionu RIPE) wypisuje obiekt rejestru, origin AS, status RPKI i najbardziej szczegółowy wiersz geofeedu dla prefiksu, korzystając z RIPE Database i RIPEstat. Uruchomiliśmy go na prefiksach DCXV, prefiksach dokumentacyjnych i w przypadkach błędów; dopasowanie do feedu sprawdzono też offline na pliku przykładowym.
#!/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])
Chcesz zobaczyć valid i wiersz feedu dla swojego prefiksu. "NO entry covers this prefix" oznacza, że dostawcy czytający Twój feed pominą blok.
Dokąd wysyłać poprawki
Korzystaj z aktualnego kanału każdego dostawcy; poprawka u jednego nie poprawia pozostałych. Dokumentację sprawdzono 2026-10-14.
| Dostawca | Kanał | Co mówi dokumentacja |
|---|---|---|
| MaxMind | Jednorazowe formularze; GeoIP Exchange dla operatorów | Przyjmuje geofeedy RFC 8805 i RFC 9632, przegląd raz na dzień roboczy; brak daty wydania |
| IPinfo | Strona poprawek; geofeedy | Wpis w społeczności (2026-02-05): najpierw pomiary, geofeedy selektywnie |
| DB-IP | Link zgłoszenia przy wyniku; zbiorczo przez formularz kontaktowy | Zmiana we wpisie WHOIS rejestru RIR zwykle uruchamia odświeżenie; geofeed to kolejna droga |
| IP2Location | Kontakt i raport o dokładności danych | Terminy wydań wg licencji; brak publicznej procedury poprawek i geofeedów |
| Formularz zgłoszenia IP w Pomocy Search | Aktualizacje mogą trwać ponad miesiąc ("may take more than a month"); brak indywidualnej odpowiedzi |
Opublikuj geofeed i podlinkuj go
Geofeed to plik CSV zdefiniowany w RFC 8805: ip_prefix,alpha2code,region,city. Prefiksy zagnieżdżone są dozwolone, wygrywa najbardziej szczegółowy. RFC wymaga UTF-8 i końców linii CRLF, uznaje kod pocztowy za przestarzały (pomiń go) i pozwala odbiorcom traktować dane tylko jako wskazówkę. Minimalny plik z prefiksami dokumentacyjnymi:
# prefix,country,region,city
192.0.2.0/24,CZ,CZ-10,Prague
2001:db8::/32,CZ,CZ-10,Prague
Umieść plik pod HTTPS i dodaj jedną linię geofeed: https://example.net/geofeed.csv do swojego inetnum lub inet6num; atrybut jest opcjonalny i pojedynczy. RFC 9632 każe odbiorcom użyć najbardziej szczegółowego obiektu z geofeedem, a inne wskazówki, jak country:, zignorować. Definiuje też opcjonalny podpis RPKI pliku; nie sprawdzaliśmy, którzy dostawcy go weryfikują. Po transferze przeczytaj obiekt: linia geofeed: pozostawiona przez sprzedawcę wskazuje plik, którego nie kontrolujesz.
Plan działań dla nowego posiadacza
- Zbierz dowody. Wpis w rejestrze wskazujący Ciebie jako posiadacza, listę CIDR i dowód, gdzie działają serwery.
- Popraw swoją stronę. Skoryguj linię
geofeed:, opublikuj plik, uruchom skrypt. - Zgłoś u każdego dostawcy. Po jednym zgłoszeniu, z adresem feedu. Podawaj tylko rzeczywistą lokalizację: dostawcy mogą ją porównać z własnymi pomiarami.
- Prowadź dziennik. Numer zgłoszenia, data, dostawca, prefiks, odpowiedź.
- Sprawdź ponownie później. Nikt nie obiecuje terminu, więc nie planuj na nim startu.
Objaw, przyczyna, weryfikacja, działanie
| Objaw | Możliwa przyczyna | Weryfikacja | Działanie |
|---|---|---|---|
| Kilku dostawców pokazuje poprzedni kraj | Brak geofeedu lub jeszcze nieodczytany | Skrypt: jest linia geofeed: i pasujący wiersz? |
Opublikować feed, potem po poprawce u każdego dostawcy |
| Jeden dostawca idzie za rejestrem, nie za feedem | Ten dostawca nie używa feedów | Jego dokumentacja i zapytanie | Wysłać poprawkę z adresem feedu |
| Feed działa, a stare dane zostają | Opóźnienie wydania, błąd pobierania lub pomiar się nie zgadza | HTTPS osiągalny, prefiks pokryty, brak konfliktowego zagnieżdżonego wiersza | Zapytać dostawcę, zachować zgłoszenie, sprawdzić później |
| Myli się tylko jeden CDN, bank lub usługa płatnicza | Używa własnych danych: Cloudflare na przykład aktualizuje bazę kilka razy w tygodniu i nie może zagwarantować zgodności z innymi dostawcami; silniki ryzyka mogą ważyć też inne sygnały | Zapytać, jakie źródło stosuje | Poprawić to źródło, potem zgłosić usłudze |
| Kraj dobry, miasto złe | W feedzie brak miasta lub pomiar różni się | Kolumna city w feedzie | Dodać region i miasto, potem zapytać ponownie |

Oszacuj ryzyko przed zakupem
Czarne listy i nadużycia są w liście kontrolnej due diligence; tu tylko geolokalizacja. Sprawdź prefiks u dwóch lub trzech dostawców już teraz, przeczytaj jego inetnum (country: i każdy adres geofeed:) i ustal, kto kontroluje ten plik. Uzgodnij w umowie, że sprzedawca przekaże lub usunie odwołanie do feedu przy zamknięciu.
Następny krok
Nie wiesz, gdzie jest luka? Wyślij do nas zapytanie o transfer IPv4 albo napisz na ipv4@dcxv.com, podając prefiks i objaw. Nie obiecujemy, kiedy dostawca zaktualizuje dane.
