0
<< предыдущая заметкаследующая заметка >>
21 октября 2024
Фейковый NTP-сервер

UPD: Дружище Андрей Нигматуллин предложил нормальное решение через DynDNS и даже помог разобраться и настроить, спасибо ему!

Итак, задача: у вас есть говнороутер и провайдер, который выдает ему внешний (это важно) IP, но постоянно его меняет. А вы хотите, чтобы этот IP всегда отзывался по адресу в вашем родном домене, скажем oops.lleo.me (все имена здесь и ниже условные). У вашего роутера есть раздел динамического обновления адреса DDNS, но там только 4 варианта. Но среди них есть afraid.org!

Решение:

Допустим, у вас домен lleo.me на CloudFlare.com (можно и без него, но с ним лучше)
Выбираем поддоменное имя для своего lleo.me, например: govnorouter.lleo.me
На CloudFlare.com в разделе DNS сайта lleo.me создаем новую запись типа NS:

Type: NS
Name: govnorouter
Nameserver: ns1.afraid.org

Идем на https://afraid.org и создаем бесплатную запись «Sign up Free». Поле «userID» — пишите любое латинское слово, надеюсь там такого юзера нет. Подтвердите email, и вы залогинены. Теперь на afraid.org (дизайн там даже не 90-е, а 80-е, под браузер lynx) идем в «Domains», «Add domain» — и там прописываем свой govnorouter.lleo.me (Shared:Public я выбрал на всякий случай).

Придумываем домен еще более нижнего уровня для своего govnorouter.lleo.me, например real.govnorouter.lleo.me На afraid.org в разделе «Subdomains» нажимаем «Add».
Но, сцуко, не тот Add, который внизу, а тот Add, который в строке с доменом govnorouter.lleo.me
И в открывшемся меню пишем:

Type: A
Subdomain: real
Domain: govnorouter.lleo.me

После чего в разделе «Dynamic DNS» можно найти ключ. Например посмотреть «Direct URL»
для своего real.govnorouter.lleo.me, там покажет ключ:

httрs://freedns.afraid.org/dynamic/update.php?dFhXQzRtRWltMkpONzRQMOQ1BxOjIzMzU1NTg2

Собственно, каждый, кто постучится по этой ссылке, пропишет вам свой IP.

Теперь идем в админку своего говнороутера. Выбираем DDNS чотатакое.afraid.com и заполняем поля c с логином и паролем guest (не спрашивайте):

Login: guest
Password: guest
domain_name: real.govnorouter.lleo.me
Hash Value: dFhXQzRtRWltMkpONzRQMOQ1BxOjIzMzU1NTg2

Если в вашем роутере нет поля «Hash Value» — ищите доку на afraid.org, там что-то было про «через запятую» в каком-то другом поле.

Короче, теперь роутер обновляет свой IP для домена четвертого уровня, согласно NS-записи для домена третьего уровня. На хера такое длинное? Придумываем на CloudFlare нормальное короткое имя, чтоб набирать удобно: oops.lleo.me и вписываем:

Type: CNAME
Name: oops
Target: real.govnorouter.lleo.me
Proxied: NO

Вот теперь норм. Мы получили собственное имя в своем собственном домене oops.lleo.me, которое всегда указывает на IP нужного нам далекого устройства. А даже если afraid.org когда-нибудь поломается (посылаю им лучи здоровья и процветания), имя-то ваше, оно никуда не пропадет, придумаем другой способ его обновлять.

Было:


Забавную проблему решаю в свободные от работы полчасика. Итак, есть в офисе интернет-роутер (от провайдера — ни сменить, ни перепрошить), ему выдается внешний IP, но динамический. И его надо знать. Обычно я динамические IP подвязываю к поддомену lleo.me, автоматически меняя скриптиком через API CloudFlare. Но для этого адрес надо сначала узнать! А для этого надо, чтобы из той сети кто-то постучался на любой из серверов, куда у меня есть доступ.

1. Первое что приходит на ум — поставить в офис маленькую Raspberry, я лучше даже ESP12. Этим, чую, в итоге и кончится. Это очевидно. Но это не спортивно! Это потом. Так что пока никаких дополнительных устройств ставить не буду, попробую другие пути.

2. В офисе есть свой девайс — погодная станция от Юры, которая раз в час посылает телеметрию на его сайт. Перепрограммировать ее на какие-то еще обращения к другим сайтам может только Юра. Но у меня зато есть доступ к его сайту, где приемник телеметрии я сам ему писал когда-то на PHP. Так что не вопрос вставить в тот приемный скрипт закладку, что для станции номер 123 фиксировать ее IP. Казалось бы, что может пойти не так? Выясняется, что хостер у Юры как-то так криво настроен, что передает в nginx все запросы от имени своего собственного IP и никаких хедеров и прочих следов о реальном IP тупо не дает. Обычно это пофиг, потому что нормальные люди свои проксируют через CloudFlare, а тот сам выставляет нужный хедер. Но Юра сайт через CloudFlare не прописал и переносить категорически не хочет — у меня, говорит, всё работает, как бы чего не сломалось.

3. Окей, копаемся в самом роутере. Роутер примитивный. У него, конечно, есть свой раздел DDNS, и там есть на выбор 4 сервиса, но свой собственный url указать нельзя. А пользоваться чужими сервисами DDNS я раз и навсегда зарекся — меня когда-то кинул homeip, просто тупо отобрал домен, и мне пришлось переписывать все мои программы и сервисы, которые были на то имя жестко завязаны. Так что чужие DDNS я отныне никогда использовать не буду — ни деньги этим пидарасам платить не стану, ни бесплатно регистрироваться не буду, это принцип.

4. Единственное, что есть в роутере — это сервис определения точного времени NTP. На хера он тупому роутеру нужен — загадка, но он есть, и там можно вводить свои имена доменов. Вау! Вот это задача по-настоящему интересная!

Итак, вписываю в качестве NTP-сервера fake-ntp.lleo.me Там быстро набрасываю (с советами ChatGPT) софтинку на питоне, которая ловит обращения UDP (пробрасываю дома порт 123 на 8123), пишу логи, а для себя даже отправляю в Телеграм.

[показать спрятанное]

<?php
import socket
import logging
import requests
import urllib
.parse
import os
import time
import threading

# Настроим логирование
logging.basicConfig(filename='/home/work/NTP-fake/ntp_requests.log'level=logging.INFOformat='%(asctime)s — %(message)s')

# Создаем UDP-сокет
sock socket.socket(socket.AF_INETsocket.SOCK_DGRAM)
server_address = ('0.0.0.0'8123)  # Слушаем на всех интерфейсах на порту 8123
sock.bind(server_address)
print(
"Listening for NTP packets on port 8123...")

# Создаем директорию для временных файлов, если она не существует
TEMP_DIR "/tmp/NTP-fake"
if not os.path.exists(TEMP_DIR):
    os.makedirs(TEMP_DIR)

# Функция для отправки GET-запроса в мой канал в Телеграм
def send_get_request(message):
    encoded_message = urllib.parse.quote(message, safe='')
    url = f"https://lleo.me/bot/telegram.php?password=lleo123&soft=ntpfake&message={encoded_message}"
    
try:
        
response requests.get(url)
        if 
response.status_code == 200:
            print(
f"Notification sent: {message}")
        else:
            print(f"Failed to notify: {response.status_code}"
)
    
except requests.RequestException as e:
        print(
f"Error sending notification: {e}")

# Функция для создания файла с содержимым
def create_message_file(ip, message):
    file_path = os.path.join(TEMP_DIR, ip)
    with open(file_path, 'w') as f:
        f.write(message)

# Функция для проверки и отправки старых файлов
def process_old_files():
    while True:
        current_time = time.time()
        for filename in os.listdir(TEMP_DIR):
            file_path = os.path.join(TEMP_DIR, filename)
            # Проверяем, если файл старше 10 секунд
            if current_time — os.path.getmtime(file_path) > 10:
                with open(file_path, 'r') as f:
                    message = f.read()
                send_get_request(message)
                os.remove(file_path)  # Удаляем файл после отправки

        time.sleep(1)  # Проверяем папку каждую секунду

# Запускаем процесс обработки старых файлов в отдельном потоке
threading.Thread(target=process_old_files, daemon=True).start()

# Основной цикл обработки NTP-запросов
while True:
    try:
        # Получаем данные от клиента
        data, address = sock.recvfrom(1024)  # Получаем пакет (максимум 1024 байта)
        ip = address[0]
        port = address[1]

        message = f"\nNTP-fake\nIP:{ip} Port:{port}"

        
# Логируем запрос
        
logging.info(f"NTP request from IP: {ip}, Port: {port}")
        print(f"Received packet from {ip}:{port}"
)

        
# Создаем файл с именем IP и записываем encoded_message
        
create_message_file(ipmessage)

    
except Exception as e:
        
logging.error(f"Error occurred: {e}")
        print(f"Error occurred: {e}"
)

Прописываю как демон:

[показать спрятанное]
install.sh:

sudo systemctl stop ntp-fake.service
sudo systemctl disable ntp-fake.service
sudo rm /etc/systemd/system/ntp-fake.service
sudo ln -s /home/work/NTP-fake/ntp-fake.service /etc/systemd/system/ntp-fake.service
sudo systemctl daemon-reload
sudo systemctl enable ntp-fake.service
sudo systemctl start ntp-fake.service
sudo systemctl status ntp-fake.service

/home/work/NTP-fake/ntp-fake.service:

[Unit]
Description=NTP Fake Service (logs IPs)
After=network.target

[Service]
ExecStart=/usr/bin/python3 /home/work/NTP-fake/ntp2.py
WorkingDirectory=/home/work/NTP-fake
Restart=always
User=lleo
Group=lleo
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=ntp-fake

[Install]
WantedBy=multi-user.target

Проверяю с любого другого внешнего сервера:

sudo ntpdate fake-ntp.lleo.me

Всё работает! Приходит запрос с порта 123, хотя ответ, понятно, мой сервер не передает.

Но в итоге результат логов за трое суток: целые дни стучатся по сотне левых мудацких роботов с самых разных лохматых портов (33007, 38388, 51319)! А роутер со своего IP пока не зашел ни разу! Ни после резета, никак.

Вот и думаю: то ли в нем выключен этот NTP вообще, то ли он его запускает раз в месяц или по какой-то неожиданной надобности, то ли зря я вписал свой адрес первой строчкой, а вторую, запасную, оставил, как была, — может, он вторую строчку запомнил как-то как основную и по первой уже не пытается постучать?

<< предыдущая заметка следующая заметка >>
пожаловаться на эту публикацию администрации портала
архив понравившихся мне ссылок

Комментарии к этой заметке скрываются - они будут видны только вам и мне.

Оставить комментарий