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

🔄 Своя Dropbox-альтернатива: Syncthing

🔄 Своя Dropbox-альтернатива: Syncthing

🧠 Зачем? Облачные сервисы — удобно, но: * не хочется платить Google/Dropbox за хранение своих файлов * хочется моментально синхронизировать фото, документы и заметки между устройствами * и делать это на своём сервере, без отправки данных «в облако» 👉 Решение — Syncthing: децентрализованный, зашифрованный, open source-синк между любыми устройствами. 🚀 Что ты получишь? * 📂 Автосинк папок между сервером,

🎧 Свой подкаст-сервер за 5 минут: Podgrab

🎧 Свой подкаст-сервер за 5 минут: Podgrab

✨ Зачем? Подкасты — отличный способ учиться, развлекаться и быть в курсе мира. Но что, если: * Хочется слушать подкасты офлайн * Хочется архивировать любимые шоу * Не устраивают сторонние сервисы, реклама и трекеры Решение: Podgrab — простой подкаст-граббер, который автоматически скачивает новые выпуски с любого RSS. А в связке с Audiobookshelf ты получаешь полноценный медиасервер.

Безопасное управление конфигурациями в Ansible: Полное руководство по использованию rescue и always

Безопасное управление конфигурациями в Ansible: Полное руководство по использованию rescue и always

Введение: Почему это важно В мире DevOps и системного администрирования существует простое правило: всё ломается. Особенно в самый неподходящий момент. Когда вы изменяете конфигурацию критического сервиса (например, Nginx), цена ошибки может быть очень высока — от простого даунтайма до потери данных. Ansible предлагает элегантное решение для безопасного внесения изменений через механизм

Использование ~/.ssh/authorized_keys для управления входящими SSH-соединениями

Использование ~/.ssh/authorized_keys для управления входящими SSH-соединениями

Файл ~/.ssh/authorized_keys позволяет настроить команды, которые будут выполняться при входящих SSH-соединениях. Это полезный инструмент для управления доступом и обеспечения безопасности, особенно при работе с резервным копированием данных. Настройка резервного копирования с использованием authorized_keys В данном примере рассматривается использование authorized_keys для настройки резервного копирования базы данных Bacula