有条件地重写和过滤 A 记录请求的 DNS 代理服务器
项目描述
dns 重写代理

有条件地重写和过滤 A 记录请求的 DNS 代理服务器。用 Python 编写,所有代码都在一个模块中,并且有一个依赖项 aiodnsresolver。
CNAME 由代理跟踪并解析为 IP 地址,并且永远不会返回给客户端。
安装
pip install dnsrewriteproxy
用法
默认情况下,代理将侦听端口 53,并将请求代理到/etc/resolv.conf. 但是,默认情况下,所有请求都会在没有明确规则的情况下被阻止,因此对于代理请求,您必须至少配置一个重写规则。
from dnsrewriteproxy import DnsProxy
# Proxy all incoming A record requests without any rewriting
start = DnsProxy(rules=((r'(^.*$)', r'\1'),))
# Run proxy, accepting UDP requests on port 53
await start()
该rules参数必须是元组的可迭代[例如列表或元组],其中每个元组是正则表达式模式/替换对,在后台传递给re.subn。在来自域的下游的每个传入 DNS 请求上
- 这个列表被迭代;
- 第一条匹配传入域名的规则用于改写域,向上游DNS服务器查询A记录,下游返回这些记录或错误码;
- 如果没有规则匹配,则下游返回 REFUSED 响应。
REFUSED 的响应是为了让客户端能够帮助区分代理上的配置问题、代理不工作或不可联系,以及域实际上不存在。
www.source.com因此,要重写to的所有查询www.target.com,并拒绝代理任何其他查询,您可以使用以下配置。
start = DnsProxy(rules=(
(r'^www\.source\.com$', r'www.target.com'),
))
或者,进行相同的重写,但要允许所有其他请求,您可以使用以下内容。
start = DnsProxy(rules=(
(r'^www\.source\.com$', r'www.target.com'),
(r'(^.*$)', r'\1'),
))
要代理到 中指定的服务器以外的服务器/etc/resolv.conf,您可以通过自定义Resolver传递get_resolver。
from aiodnsresolver import Resolver
from dnsrewriteproxy import DnsProxy
def get_resolver():
async def get_nameservers(_, __):
for _ in range(0, 5):
yield (0.5, ('8.8.8.8', 53))
return Resolver(get_nameserver=get_nameservers)
start = DnsProxy(
rules=((r'(^.*$)', r'\1'),),
get_resolver=get_resolver,
)
服务器生命周期
在上面的例子await start()中,服务器刚刚开始监听就完成了。协程start返回底层任务以控制服务器生命周期。一个任务可以看作是一个“异步线程”;这被暴露以允许服务器坐在一个更大的 asyncio Python 程序中,该程序可能具有特定的启动/关闭过程。
永远奔跑
通过等待此任务,您可以永远运行服务器[或直到它遇到一些不可恢复的错误]。
from dnsrewriteproxy import DnsProxy
start = DnsProxy(rules=((r'(^.*$)', r'\1'),))
server_task = await start()
# Waiting here until the server is stopped
await server_task
停止服务器
要停止服务器,您可以cancel返回任务。
from dnsrewriteproxy import DnsProxy
start = DnsProxy(rules=((r'(^.*$)', r'\1'),))
proxy_task = await start()
# ... Receive requests
# Initiate stopping: new requests will not be processed...
proxy_task.cancel()
try:
# ... and we wait until previously received requests have been processed
await proxy_task
except asyncio.CancelledError:
pass
优雅关机示例
下面是一个在 SIGINT 或 SIGTERM 上进行正常关闭的服务器的完整示例。
import asyncio
import signal
from dnsrewriteproxy import (
DnsProxy,
)
async def async_main():
start = DnsProxy(rules=((r'(^.*$)', r'\1'),))
proxy_task = await start()
loop = asyncio.get_running_loop()
loop.add_signal_handler(signal.SIGINT, proxy_task.cancel)
loop.add_signal_handler(signal.SIGTERM, proxy_task.cancel)
try:
await proxy_task
except asyncio.CancelledError:
pass
asyncio.run(async_main())
print('End of program')
项目详情
dnsrewriteproxy -0.0.16.tar.gz 的哈希值
| 算法 | 哈希摘要 | |
|---|---|---|
| SHA256 | 3af972f59d6170d3c0aaa61a41cf7b057c06ca13c7907cfa4b9f609b62c7622d |
|
| MD5 | d7c83fbf5d8ecf87693916996da795a6 |
|
| 布莱克2-256 | cb8aef873ba8f1ab5cfc02c741ceb9cd95b5fd8ec96638f66f00a8f39ab9621e |
dnsrewriteproxy -0.0.16-py3-none-any.whl 的哈希值
| 算法 | 哈希摘要 | |
|---|---|---|
| SHA256 | 82c11126bc2031df475cb4d891ca91517990defc2a75f23ab20024d5537e5443 |
|
| MD5 | e4ba489ad5696c8877399cea1e501ea5 |
|
| 布莱克2-256 | cfdfb88063af67239386dd9e9b7cfa6580a4332f007b82c92a49abb266559fcb |