GeoIP в Clickhouse

GeoIP в Clickhouse
Photo by Sunder Muthukumaran / Unsplash

Не всегда есть возможность использовать MaxMind GeoIP базы. В ClickHouse я прикрутил для себя вот такой вариант:

-- 1. Создаем базу данных для GeoIP
CREATE DATABASE IF NOT EXISTS geoip;

-- 2. Переключаемся на базу geoip
USE geoip;

-- 3. Создаем таблицу для стран (самый быстрый вариант)
CREATE TABLE ip_country (
    ip_start UInt32,
    ip_end UInt32,
    country_code FixedString(2)
) ENGINE = MergeTree()
ORDER BY ip_start
SETTINGS index_granularity = 8192;

-- 4. Загружаем данные из готового CSV (GeoLite2)
-- Используем URL функцию для прямой загрузки
INSERT INTO ip_country 
SELECT 
    IPv4StringToNum(ip_range_start) as ip_start,
    IPv4StringToNum(ip_range_end) as ip_end,
    country_code
FROM url(
    'https://cdn.jsdelivr.net/npm/@ip-location-db/geolite2-country/geolite2-country-ipv4.csv',
    'CSV',
    'ip_range_start String, ip_range_end String, country_code String'
) WHERE country_code != '';

-- 5. Создаем расширенную таблицу с дополнительной информацией о странах
CREATE TABLE country_info (
    country_code FixedString(2),
    country_name String,
    continent_code FixedString(2),
    continent_name String
) ENGINE = MergeTree()
ORDER BY country_code;

-- 6. Заполняем справочник стран
INSERT INTO country_info VALUES
('AD', 'Andorra', 'EU', 'Europe'),
('AE', 'United Arab Emirates', 'AS', 'Asia'),
('AF', 'Afghanistan', 'AS', 'Asia'),
('AG', 'Antigua and Barbuda', 'NA', 'North America'),
('AI', 'Anguilla', 'NA', 'North America'),
('AL', 'Albania', 'EU', 'Europe'),
('AM', 'Armenia', 'AS', 'Asia'),
('AO', 'Angola', 'AF', 'Africa'),
('AQ', 'Antarctica', 'AN', 'Antarctica'),
('AR', 'Argentina', 'SA', 'South America'),
('AS', 'American Samoa', 'OC', 'Oceania'),
('AT', 'Austria', 'EU', 'Europe'),
('AU', 'Australia', 'OC', 'Oceania'),
('AW', 'Aruba', 'NA', 'North America'),
('AX', 'Åland Islands', 'EU', 'Europe'),
('AZ', 'Azerbaijan', 'AS', 'Asia'),
('BA', 'Bosnia and Herzegovina', 'EU', 'Europe'),
('BB', 'Barbados', 'NA', 'North America'),
('BD', 'Bangladesh', 'AS', 'Asia'),
('BE', 'Belgium', 'EU', 'Europe'),
('BF', 'Burkina Faso', 'AF', 'Africa'),
('BG', 'Bulgaria', 'EU', 'Europe'),
('BH', 'Bahrain', 'AS', 'Asia'),
('BI', 'Burundi', 'AF', 'Africa'),
('BJ', 'Benin', 'AF', 'Africa'),
('BL', 'Saint Barthélemy', 'NA', 'North America'),
('BM', 'Bermuda', 'NA', 'North America'),
('BN', 'Brunei Darussalam', 'AS', 'Asia'),
('BO', 'Bolivia', 'SA', 'South America'),
('BQ', 'Bonaire, Sint Eustatius and Saba', 'NA', 'North America'),
('BR', 'Brazil', 'SA', 'South America'),
('BS', 'Bahamas', 'NA', 'North America'),
('BT', 'Bhutan', 'AS', 'Asia'),
('BV', 'Bouvet Island', 'AN', 'Antarctica'),
('BW', 'Botswana', 'AF', 'Africa'),
('BY', 'Belarus', 'EU', 'Europe'),
('BZ', 'Belize', 'NA', 'North America'),
('CA', 'Canada', 'NA', 'North America'),
('CC', 'Cocos (Keeling) Islands', 'AS', 'Asia'),
('CD', 'Congo, The Democratic Republic of the', 'AF', 'Africa'),
('CF', 'Central African Republic', 'AF', 'Africa'),
('CG', 'Congo', 'AF', 'Africa'),
('CH', 'Switzerland', 'EU', 'Europe'),
('CI', 'Côte d''Ivoire', 'AF', 'Africa'),
('CK', 'Cook Islands', 'OC', 'Oceania'),
('CL', 'Chile', 'SA', 'South America'),
('CM', 'Cameroon', 'AF', 'Africa'),
('CN', 'China', 'AS', 'Asia'),
('CO', 'Colombia', 'SA', 'South America'),
('CR', 'Costa Rica', 'NA', 'North America'),
('CU', 'Cuba', 'NA', 'North America'),
('CV', 'Cape Verde', 'AF', 'Africa'),
('CW', 'Curaçao', 'NA', 'North America'),
('CX', 'Christmas Island', 'AS', 'Asia'),
('CY', 'Cyprus', 'AS', 'Asia'),
('CZ', 'Czech Republic', 'EU', 'Europe'),
('DE', 'Germany', 'EU', 'Europe'),
('DJ', 'Djibouti', 'AF', 'Africa'),
('DK', 'Denmark', 'EU', 'Europe'),
('DM', 'Dominica', 'NA', 'North America'),
('DO', 'Dominican Republic', 'NA', 'North America'),
('DZ', 'Algeria', 'AF', 'Africa'),
('EC', 'Ecuador', 'SA', 'South America'),
('EE', 'Estonia', 'EU', 'Europe'),
('EG', 'Egypt', 'AF', 'Africa'),
('EH', 'Western Sahara', 'AF', 'Africa'),
('ER', 'Eritrea', 'AF', 'Africa'),
('ES', 'Spain', 'EU', 'Europe'),
('ET', 'Ethiopia', 'AF', 'Africa'),
('FI', 'Finland', 'EU', 'Europe'),
('FJ', 'Fiji', 'OC', 'Oceania'),
('FK', 'Falkland Islands (Malvinas)', 'SA', 'South America'),
('FM', 'Micronesia, Federated States of', 'OC', 'Oceania'),
('FO', 'Faroe Islands', 'EU', 'Europe'),
('FR', 'France', 'EU', 'Europe'),
('GA', 'Gabon', 'AF', 'Africa'),
('GB', 'United Kingdom', 'EU', 'Europe'),
('GD', 'Grenada', 'NA', 'North America'),
('GE', 'Georgia', 'AS', 'Asia'),
('GF', 'French Guiana', 'SA', 'South America'),
('GG', 'Guernsey', 'EU', 'Europe'),
('GH', 'Ghana', 'AF', 'Africa'),
('GI', 'Gibraltar', 'EU', 'Europe'),
('GL', 'Greenland', 'NA', 'North America'),
('GM', 'Gambia', 'AF', 'Africa'),
('GN', 'Guinea', 'AF', 'Africa'),
('GP', 'Guadeloupe', 'NA', 'North America'),
('GQ', 'Equatorial Guinea', 'AF', 'Africa'),
('GR', 'Greece', 'EU', 'Europe'),
('GS', 'South Georgia and the South Sandwich Islands', 'AN', 'Antarctica'),
('GT', 'Guatemala', 'NA', 'North America'),
('GU', 'Guam', 'OC', 'Oceania'),
('GW', 'Guinea-Bissau', 'AF', 'Africa'),
('GY', 'Guyana', 'SA', 'South America'),
('HK', 'Hong Kong', 'AS', 'Asia'),
('HM', 'Heard Island and McDonald Islands', 'AN', 'Antarctica'),
('HN', 'Honduras', 'NA', 'North America'),
('HR', 'Croatia', 'EU', 'Europe'),
('HT', 'Haiti', 'NA', 'North America'),
('HU', 'Hungary', 'EU', 'Europe'),
('ID', 'Indonesia', 'AS', 'Asia'),
('IE', 'Ireland', 'EU', 'Europe'),
('IL', 'Israel', 'AS', 'Asia'),
('IM', 'Isle of Man', 'EU', 'Europe'),
('IN', 'India', 'AS', 'Asia'),
('IO', 'British Indian Ocean Territory', 'AS', 'Asia'),
('IQ', 'Iraq', 'AS', 'Asia'),
('IR', 'Iran, Islamic Republic of', 'AS', 'Asia'),
('IS', 'Iceland', 'EU', 'Europe'),
('IT', 'Italy', 'EU', 'Europe'),
('JE', 'Jersey', 'EU', 'Europe'),
('JM', 'Jamaica', 'NA', 'North America'),
('JO', 'Jordan', 'AS', 'Asia'),
('JP', 'Japan', 'AS', 'Asia'),
('KE', 'Kenya', 'AF', 'Africa'),
('KG', 'Kyrgyzstan', 'AS', 'Asia'),
('KH', 'Cambodia', 'AS', 'Asia'),
('KI', 'Kiribati', 'OC', 'Oceania'),
('KM', 'Comoros', 'AF', 'Africa'),
('KN', 'Saint Kitts and Nevis', 'NA', 'North America'),
('KP', 'Korea, Democratic People''s Republic of', 'AS', 'Asia'),
('KR', 'Korea, Republic of', 'AS', 'Asia'),
('KW', 'Kuwait', 'AS', 'Asia'),
('KY', 'Cayman Islands', 'NA', 'North America'),
('KZ', 'Kazakhstan', 'AS', 'Asia'),
('LA', 'Lao People''s Democratic Republic', 'AS', 'Asia'),
('LB', 'Lebanon', 'AS', 'Asia'),
('LC', 'Saint Lucia', 'NA', 'North America'),
('LI', 'Liechtenstein', 'EU', 'Europe'),
('LK', 'Sri Lanka', 'AS', 'Asia'),
('LR', 'Liberia', 'AF', 'Africa'),
('LS', 'Lesotho', 'AF', 'Africa'),
('LT', 'Lithuania', 'EU', 'Europe'),
('LU', 'Luxembourg', 'EU', 'Europe'),
('LV', 'Latvia', 'EU', 'Europe'),
('LY', 'Libya', 'AF', 'Africa'),
('MA', 'Morocco', 'AF', 'Africa'),
('MC', 'Monaco', 'EU', 'Europe'),
('MD', 'Moldova, Republic of', 'EU', 'Europe'),
('ME', 'Montenegro', 'EU', 'Europe'),
('MF', 'Saint Martin (French part)', 'NA', 'North America'),
('MG', 'Madagascar', 'AF', 'Africa'),
('MH', 'Marshall Islands', 'OC', 'Oceania'),
('MK', 'Macedonia, Republic of', 'EU', 'Europe'),
('ML', 'Mali', 'AF', 'Africa'),
('MM', 'Myanmar', 'AS', 'Asia'),
('MN', 'Mongolia', 'AS', 'Asia'),
('MO', 'Macao', 'AS', 'Asia'),
('MP', 'Northern Mariana Islands', 'OC', 'Oceania'),
('MQ', 'Martinique', 'NA', 'North America'),
('MR', 'Mauritania', 'AF', 'Africa'),
('MS', 'Montserrat', 'NA', 'North America'),
('MT', 'Malta', 'EU', 'Europe'),
('MU', 'Mauritius', 'AF', 'Africa'),
('MV', 'Maldives', 'AS', 'Asia'),
('MW', 'Malawi', 'AF', 'Africa'),
('MX', 'Mexico', 'NA', 'North America'),
('MY', 'Malaysia', 'AS', 'Asia'),
('MZ', 'Mozambique', 'AF', 'Africa'),
('NA', 'Namibia', 'AF', 'Africa'),
('NC', 'New Caledonia', 'OC', 'Oceania'),
('NE', 'Niger', 'AF', 'Africa'),
('NF', 'Norfolk Island', 'OC', 'Oceania'),
('NG', 'Nigeria', 'AF', 'Africa'),
('NI', 'Nicaragua', 'NA', 'North America'),
('NL', 'Netherlands', 'EU', 'Europe'),
('NO', 'Norway', 'EU', 'Europe'),
('NP', 'Nepal', 'AS', 'Asia'),
('NR', 'Nauru', 'OC', 'Oceania'),
('NU', 'Niue', 'OC', 'Oceania'),
('NZ', 'New Zealand', 'OC', 'Oceania'),
('OM', 'Oman', 'AS', 'Asia'),
('PA', 'Panama', 'NA', 'North America'),
('PE', 'Peru', 'SA', 'South America'),
('PF', 'French Polynesia', 'OC', 'Oceania'),
('PG', 'Papua New Guinea', 'OC', 'Oceania'),
('PH', 'Philippines', 'AS', 'Asia'),
('PK', 'Pakistan', 'AS', 'Asia'),
('PL', 'Poland', 'EU', 'Europe'),
('PM', 'Saint Pierre and Miquelon', 'NA', 'North America'),
('PN', 'Pitcairn', 'OC', 'Oceania'),
('PR', 'Puerto Rico', 'NA', 'North America'),
('PS', 'Palestine, State of', 'AS', 'Asia'),
('PT', 'Portugal', 'EU', 'Europe'),
('PW', 'Palau', 'OC', 'Oceania'),
('PY', 'Paraguay', 'SA', 'South America'),
('QA', 'Qatar', 'AS', 'Asia'),
('RE', 'Réunion', 'AF', 'Africa'),
('RO', 'Romania', 'EU', 'Europe'),
('RS', 'Serbia', 'EU', 'Europe'),
('RU', 'Russian Federation', 'EU', 'Europe'),
('RW', 'Rwanda', 'AF', 'Africa'),
('SA', 'Saudi Arabia', 'AS', 'Asia'),
('SB', 'Solomon Islands', 'OC', 'Oceania'),
('SC', 'Seychelles', 'AF', 'Africa'),
('SD', 'Sudan', 'AF', 'Africa'),
('SE', 'Sweden', 'EU', 'Europe'),
('SG', 'Singapore', 'AS', 'Asia'),
('SH', 'Saint Helena, Ascension and Tristan da Cunha', 'AF', 'Africa'),
('SI', 'Slovenia', 'EU', 'Europe'),
('SJ', 'Svalbard and Jan Mayen', 'EU', 'Europe'),
('SK', 'Slovakia', 'EU', 'Europe'),
('SL', 'Sierra Leone', 'AF', 'Africa'),
('SM', 'San Marino', 'EU', 'Europe'),
('SN', 'Senegal', 'AF', 'Africa'),
('SO', 'Somalia', 'AF', 'Africa'),
('SR', 'Suriname', 'SA', 'South America'),
('SS', 'South Sudan', 'AF', 'Africa'),
('ST', 'Sao Tome and Principe', 'AF', 'Africa'),
('SV', 'El Salvador', 'NA', 'North America'),
('SX', 'Sint Maarten (Dutch part)', 'NA', 'North America'),
('SY', 'Syrian Arab Republic', 'AS', 'Asia'),
('SZ', 'Swaziland', 'AF', 'Africa'),
('TC', 'Turks and Caicos Islands', 'NA', 'North America'),
('TD', 'Chad', 'AF', 'Africa'),
('TF', 'French Southern Territories', 'AN', 'Antarctica'),
('TG', 'Togo', 'AF', 'Africa'),
('TH', 'Thailand', 'AS', 'Asia'),
('TJ', 'Tajikistan', 'AS', 'Asia'),
('TK', 'Tokelau', 'OC', 'Oceania'),
('TL', 'Timor-Leste', 'AS', 'Asia'),
('TM', 'Turkmenistan', 'AS', 'Asia'),
('TN', 'Tunisia', 'AF', 'Africa'),
('TO', 'Tonga', 'OC', 'Oceania'),
('TR', 'Turkey', 'AS', 'Asia'),
('TT', 'Trinidad and Tobago', 'NA', 'North America'),
('TV', 'Tuvalu', 'OC', 'Oceania'),
('TW', 'Taiwan', 'AS', 'Asia'),
('TZ', 'Tanzania, United Republic of', 'AF', 'Africa'),
('UA', 'Ukraine', 'EU', 'Europe'),
('UG', 'Uganda', 'AF', 'Africa'),
('UM', 'United States Minor Outlying Islands', 'NA', 'North America'),
('US', 'United States', 'NA', 'North America'),
('UY', 'Uruguay', 'SA', 'South America'),
('UZ', 'Uzbekistan', 'AS', 'Asia'),
('VA', 'Vatican City State', 'EU', 'Europe'),
('VC', 'Saint Vincent and the Grenadines', 'NA', 'North America'),
('VE', 'Venezuela', 'SA', 'South America'),
('VG', 'Virgin Islands, British', 'NA', 'North America'),
('VI', 'Virgin Islands, U.S.', 'NA', 'North America'),
('VN', 'Viet Nam', 'AS', 'Asia'),
('VU', 'Vanuatu', 'OC', 'Oceania'),
('WF', 'Wallis and Futuna', 'OC', 'Oceania'),
('WS', 'Samoa', 'OC', 'Oceania'),
('YE', 'Yemen', 'AS', 'Asia'),
('YT', 'Mayotte', 'AF', 'Africa'),
('ZA', 'South Africa', 'AF', 'Africa'),
('ZM', 'Zambia', 'AF', 'Africa'),
('ZW', 'Zimbabwe', 'AF', 'Africa');

Для более удобного использования теперь создадим хранимую функцию:

CREATE TABLE geoip_fast (
    ip_start UInt32,
    ip_end UInt32, 
    country_code String
) ENGINE = MergeTree()
ORDER BY ip_start;

INSERT INTO geoip_fast 
SELECT ip_start, ip_end, country_code 
FROM geoip.ip_country;

CREATE FUNCTION get_country AS (ip_string) -> 
    if(ip_string = '', 'Unknown', 
       coalesce((SELECT country_code FROM geoip_fast WHERE IPv4StringToNum(ip_string) BETWEEN ip_start AND ip_end LIMIT 1), 'Unknown'));

Использовать не просто, а очень просто:

SELECT get_country('8.8.8.8') as country;

Read more

Настройка локального SMTP-релея с Docker

Настройка локального SMTP-релея с Docker

При разработке приложений или настройке домашнего сервера часто возникает необходимость отправлять электронные письма. Вместо настройки полноценного почтового сервера можно использовать SMTP-релей, который будет пересылать письма через внешний почтовый сервис. В этой статье рассмотрим, как настроить локальный SMTP-релей с помощью Docker. Что такое SMTP-релей SMTP-релей — это промежуточный почтовый сервер, который принимает

Загрузка и использование MMDB в Clickhouse

Загрузка и использование MMDB в Clickhouse

Прошлый способ использования GeoIP данных показал, что он не очень удобен. Поэтому я зарылся в проблему и нашел более простой и действенный способ, как загрузить данные из базы MaxMind (но лучше использовать бесплатные аналоги типа IPInfo) в Clickhouse. Для этого мы берем отсюда релиз аплоадера и запускаем его вот так:

Охота на цифрового шпиона: как астроном стал первым кибердетективом

Охота на цифрового шпиона: как астроном стал первым кибердетективом

История о том, как одна бухгалтерская ошибка привела к раскрытию международной шпионской сети и заложила основы современной кибербезопасности В августе 1986 года астроном Клиффорд Столл работал системным администратором в Лаборатории Лоуренса Беркли в Калифорнии. Его обычный день был нарушен странным сообщением: компьютерная система показывала ошибку в 75 центов. Кто-то создал

Когда технологии слежки обращаются против государства: хакер наркокартеля против ФБР

Когда технологии слежки обращаются против государства: хакер наркокартеля против ФБР

В эпоху повсеместного наблюдения границы между охотником и жертвой становятся размытыми. Недавний отчет Министерства юстиции США раскрыл тревожный случай, когда сложные технологии слежки были обращены против самих правоохранительных органов с летальными последствиями. Цифровая охота на информаторов Согласно 47-страничному отчету Генерального инспектора Министерства юстиции, хакер, связанный с преступной группировкой Хоакина "