Compare commits
No commits in common. "master" and "v0.1.0" have entirely different histories.
6 changed files with 8 additions and 140 deletions
10
README.md
10
README.md
|
|
@ -1,11 +1,11 @@
|
||||||
# pydoh
|
# pydoh
|
||||||
|
|
||||||
[](https://github.com/devsavsis/pydoh/actions/workflows/ci.yml)
|
[](https://github.com/ImSavsis/pydoh/actions/workflows/ci.yml)
|
||||||
[](https://codecov.io/gh/ImSavsis/pydoh)
|
[](https://codecov.io/gh/ImSavsis/pydoh)
|
||||||
[](https://pypi.org/project/pydoh/)
|
[](https://pypi.org/project/pydoh/)
|
||||||
[](https://pypi.org/project/pydoh/)
|
[](https://pypi.org/project/pydoh/)
|
||||||
[](https://pypi.org/project/pydoh/)
|
[](https://pypi.org/project/pydoh/)
|
||||||
[](https://github.com/devsavsis/pydoh/blob/master/LICENSE)
|
[](https://github.com/ImSavsis/pydoh/blob/master/LICENSE)
|
||||||
|
|
||||||
DNS-over-HTTPS резолвер для питона. ноль зависимостей — весь HTTPS через стандартный `http.client`+`ssl`. провайдер/DPI видит только твой HTTPS к cloudflare, а не голые DNS-запросы.
|
DNS-over-HTTPS резолвер для питона. ноль зависимостей — весь HTTPS через стандартный `http.client`+`ssl`. провайдер/DPI видит только твой HTTPS к cloudflare, а не голые DNS-запросы.
|
||||||
|
|
||||||
|
|
@ -38,12 +38,6 @@ import pydoh
|
||||||
pydoh.patch_socket()
|
pydoh.patch_socket()
|
||||||
```
|
```
|
||||||
|
|
||||||
## документация
|
|
||||||
|
|
||||||
- [quickstart](docs/quickstart.md) — установка, базовое использование, свой провайдер
|
|
||||||
- [api](docs/api.md) — все функции с параметрами
|
|
||||||
- [faq](docs/faq.md) — зачем это надо, что делать если cloudflare забанят, законно ли
|
|
||||||
|
|
||||||
## фичи
|
## фичи
|
||||||
|
|
||||||
- zero deps, только stdlib
|
- zero deps, только stdlib
|
||||||
|
|
|
||||||
38
docs/api.md
38
docs/api.md
|
|
@ -1,38 +0,0 @@
|
||||||
# api
|
|
||||||
|
|
||||||
## `resolve(hostname, record_type=1, providers=None, timeout=3.0, use_cache=True) -> list[str]`
|
|
||||||
|
|
||||||
резолвит хост, возвращает список IP строками. кидает `ResolveError` если все провайдеры упали.
|
|
||||||
|
|
||||||
- `record_type` — `1` для A (по умолчанию), `28` для AAAA
|
|
||||||
- `providers` — список `Provider`, по умолчанию `pydoh.providers.DEFAULT_PROVIDERS` (cloudflare, google, quad9 по порядку)
|
|
||||||
- `timeout` — секунды на один HTTPS-запрос к одному провайдеру
|
|
||||||
- `use_cache` — читать/писать во внутренний кэш по TTL из ответа
|
|
||||||
|
|
||||||
## `resolve4(hostname, **kwargs) -> list[str]`
|
|
||||||
|
|
||||||
то же самое что `resolve(hostname, record_type=1, **kwargs)`.
|
|
||||||
|
|
||||||
## `resolve6(hostname, **kwargs) -> list[str]`
|
|
||||||
|
|
||||||
то же самое что `resolve(hostname, record_type=28, **kwargs)`.
|
|
||||||
|
|
||||||
## `patch_socket() -> None`
|
|
||||||
|
|
||||||
подменяет `socket.getaddrinfo` на версию через `resolve()`. IP-литералы (`127.0.0.1` и т.п.) пропускает мимо DoH напрямую. идемпотентно — повторный вызов ничего не ломает.
|
|
||||||
|
|
||||||
## `unpatch_socket() -> None`
|
|
||||||
|
|
||||||
возвращает оригинальный `socket.getaddrinfo`.
|
|
||||||
|
|
||||||
## `ResolveError`
|
|
||||||
|
|
||||||
исключение, вылетает из `resolve()`/`resolve4()`/`resolve6()` если ни один провайдер не ответил валидно.
|
|
||||||
|
|
||||||
## `pydoh.providers.Provider`
|
|
||||||
|
|
||||||
```python
|
|
||||||
Provider(name: str, host: str, path: str)
|
|
||||||
```
|
|
||||||
|
|
||||||
именованный tuple, описывает DoH-эндпоинт. готовые: `pydoh.CLOUDFLARE`, `pydoh.GOOGLE`, `pydoh.QUAD9`.
|
|
||||||
25
docs/faq.md
25
docs/faq.md
|
|
@ -1,25 +0,0 @@
|
||||||
# faq
|
|
||||||
|
|
||||||
## зачем это вообще
|
|
||||||
|
|
||||||
обычный DNS — незашифрованный UDP-пакет к резолверу провайдера, кто угодно на пути видит какой домен ты спрашиваешь. в РФ это самый дешёвый способ блокировки — провайдер просто не отвечает на запрос про заблокированный домен. DoH заворачивает тот же запрос в HTTPS, провайдер видит только "коннект к 1.1.1.1", а не имя домена.
|
|
||||||
|
|
||||||
## cloudflare тоже забанен, что делать
|
|
||||||
|
|
||||||
сам cloudflare (его IP-диапазоны) массово не блокируют — через него живёт куча обычных сайтов, задеть его целиком означает положить половину интернета. а вот конкретно `cloudflare-dns.com` как известный анти-цензурный эндпоинт — уже могут таргетить точечно по SNI.
|
|
||||||
|
|
||||||
если это произошло — `pydoh` сам едет на `dns.google`, потом на `dns.quad9.net` (см. `DEFAULT_PROVIDERS`), без твоего участия.
|
|
||||||
|
|
||||||
если и туда достанут — тогда нужен свой DoH-эндпоинт на домене, которого нет в блок-листах, см. [quickstart.md](quickstart.md#свой-doh-провайдер).
|
|
||||||
|
|
||||||
## а это законно
|
|
||||||
|
|
||||||
`pydoh` просто шлёт DNS-запросы другим транспортом (HTTPS вместо UDP). это тот же протокол, который сейчас включён по умолчанию в Firefox/Chrome для миллионов пользователей.
|
|
||||||
|
|
||||||
## почему не requests/httpx
|
|
||||||
|
|
||||||
zero deps — библиотека не тянет вообще ничего кроме stdlib. весь HTTPS через `http.client`+`ssl`, которые уже есть в питоне из коробки.
|
|
||||||
|
|
||||||
## поддерживает DNSSEC?
|
|
||||||
|
|
||||||
нет. и не планируется — это резолвер для обхода блокировок и приватности, а не для валидации подписей.
|
|
||||||
|
|
@ -1,63 +0,0 @@
|
||||||
# quickstart
|
|
||||||
|
|
||||||
## установка
|
|
||||||
|
|
||||||
```
|
|
||||||
pip install pydoh
|
|
||||||
```
|
|
||||||
|
|
||||||
## разовый резолвинг
|
|
||||||
|
|
||||||
```python
|
|
||||||
import pydoh
|
|
||||||
|
|
||||||
ips = pydoh.resolve("example.com")
|
|
||||||
print(ips) # ['93.184.216.34']
|
|
||||||
```
|
|
||||||
|
|
||||||
`resolve()` возвращает список строк-адресов, первый обычно и есть тот, что нужен.
|
|
||||||
|
|
||||||
## ipv6
|
|
||||||
|
|
||||||
```python
|
|
||||||
ips = pydoh.resolve6("example.com")
|
|
||||||
```
|
|
||||||
|
|
||||||
или через параметр:
|
|
||||||
|
|
||||||
```python
|
|
||||||
pydoh.resolve("example.com", record_type=28)
|
|
||||||
```
|
|
||||||
|
|
||||||
## подменить резолвинг во всём приложении
|
|
||||||
|
|
||||||
самый частый кейс — не переписывать код, а просто подменить как питон резолвит домены:
|
|
||||||
|
|
||||||
```python
|
|
||||||
import pydoh
|
|
||||||
pydoh.patch_socket()
|
|
||||||
|
|
||||||
import requests
|
|
||||||
requests.get("https://example.com") # уже через DoH, без изменений в коде requests
|
|
||||||
```
|
|
||||||
|
|
||||||
ставь `patch_socket()` в самом начале скрипта, до импорта/использования сетевых библиотек.
|
|
||||||
|
|
||||||
вернуть как было:
|
|
||||||
|
|
||||||
```python
|
|
||||||
pydoh.unpatch_socket()
|
|
||||||
```
|
|
||||||
|
|
||||||
## свой DoH-провайдер
|
|
||||||
|
|
||||||
если хочешь резолвить через свой сервер, а не через cloudflare/google/quad9:
|
|
||||||
|
|
||||||
```python
|
|
||||||
from pydoh.providers import Provider
|
|
||||||
|
|
||||||
my_provider = Provider(name="mine", host="doh.example.com", path="/dns-query")
|
|
||||||
ips = pydoh.resolve("example.com", providers=[my_provider])
|
|
||||||
```
|
|
||||||
|
|
||||||
сервер должен поддерживать [RFC 8484](https://www.rfc-editor.org/rfc/rfc8484) (`POST` с телом `application/dns-message`).
|
|
||||||
8
llms.txt
8
llms.txt
|
|
@ -6,10 +6,10 @@ Pure standard library, uses http.client and ssl for the HTTPS leg. Falls back ac
|
||||||
|
|
||||||
## Docs
|
## Docs
|
||||||
|
|
||||||
- [README](https://github.com/devsavsis/pydoh/blob/master/README.md): install, usage, feature list
|
- [README](https://github.com/ImSavsis/pydoh/blob/master/README.md): install, usage, feature list
|
||||||
- [src/pydoh/resolver.py](https://github.com/devsavsis/pydoh/blob/master/src/pydoh/resolver.py): core resolve logic with provider fallback and caching
|
- [src/pydoh/resolver.py](https://github.com/ImSavsis/pydoh/blob/master/src/pydoh/resolver.py): core resolve logic with provider fallback and caching
|
||||||
- [src/pydoh/patch.py](https://github.com/devsavsis/pydoh/blob/master/src/pydoh/patch.py): socket.getaddrinfo monkeypatch
|
- [src/pydoh/patch.py](https://github.com/ImSavsis/pydoh/blob/master/src/pydoh/patch.py): socket.getaddrinfo monkeypatch
|
||||||
- [src/pydoh/wire.py](https://github.com/devsavsis/pydoh/blob/master/src/pydoh/wire.py): minimal DNS wire format encode/decode
|
- [src/pydoh/wire.py](https://github.com/ImSavsis/pydoh/blob/master/src/pydoh/wire.py): minimal DNS wire format encode/decode
|
||||||
|
|
||||||
## Notes
|
## Notes
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,8 +23,8 @@ classifiers = [
|
||||||
]
|
]
|
||||||
|
|
||||||
[project.urls]
|
[project.urls]
|
||||||
Homepage = "https://github.com/devsavsis/pydoh"
|
Homepage = "https://github.com/ImSavsis/pydoh"
|
||||||
Issues = "https://github.com/devsavsis/pydoh/issues"
|
Issues = "https://github.com/ImSavsis/pydoh/issues"
|
||||||
|
|
||||||
[project.optional-dependencies]
|
[project.optional-dependencies]
|
||||||
dev = ["pytest", "pytest-cov", "build", "twine"]
|
dev = ["pytest", "pytest-cov", "build", "twine"]
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue