有条件地重写和过滤记录请求的DNS代理服务器
dnsrewriteprox的Python项目详细描述
dns重写代理
有条件地重写和过滤记录请求的DNS代理服务器。用Python编写,所有代码都在一个模块中,并且有一个单独的依赖项aiodnsresolver。在
CNAME由代理跟踪并解析为IP地址,并且从不返回给客户端。在
安装
pip install dnsrewriteproxy
使用
默认情况下,代理将监听端口53,并向/etc/resolv.conf
中的服务器发出代理请求。但是,默认情况下,所有请求都被阻止,没有显式规则,因此要代理请求,必须至少配置一个重写规则。在
rules
参数必须是元组的iterable[例如,列表或元组],其中每个元组都是regex模式/替换对,在幕后传递给re.subn。来自下游域的每个传入DNS请求
- 这个列表被迭代
- 第一条规则与传入域名相匹配用于重写域,向上游DNS服务器查询A记录,并向下游返回这些记录或错误代码
- 如果没有匹配的规则,则在下游返回拒绝的响应。在
拒绝的响应是故意的,以便客户机能够帮助区分代理上的配置问题、代理不工作或不可联系以及实际不存在的域。在
因此,要将www.source.com
的所有查询重写为www.target.com
,并将deject重写为代理任何其他查询,可以使用以下配置。在
start=DnsProxy(rules=((r'^www\.source\.com$',r'www.target.com'),))
或者,进行同样的重写,但是为了allow所有其他请求,可以使用以下命令。在
start=DnsProxy(rules=((r'^www\.source\.com$',r'www.target.com'),(r'(^.*$)',r'\1'),))
若要代理到/etc/resolv.conf
中指定的服务器,可以通过get_resolver
传递自定义的Resolver
。在
fromaiodnsresolverimportResolverfromdnsrewriteproxyimportDnsProxydefget_resolver():asyncdefget_nameservers(_,__):for_inrange(0,5):yield(0.5,('8.8.8.8',53))returnResolver(get_nameserver=get_nameservers)start=DnsProxy(rules=((r'(^.*$)',r'\1'),),get_resolver=get_resolver,)
服务器生命周期
在上面的例子中,await start()
在服务器开始监听之后完成。协同程序start
返回底层的task,以控制服务器的生命周期。任务可以被看作是一个“asyncio线程”;它被公开是为了允许服务器位于一个更大的asyncio Python程序中,该程序可能具有特定的启动/关闭过程。在
长跑
通过等待此任务,您可以永远运行服务器[或直到它遇到不可恢复的错误]。在
fromdnsrewriteproxyimportDnsProxystart=DnsProxy(rules=((r'(^.*$)',r'\1'),))server_task=awaitstart()# Waiting here until the server is stoppedawaitserver_task
停止服务器
要停止服务器,您可以cancel
返回的任务。在
fromdnsrewriteproxyimportDnsProxystart=DnsProxy(rules=((r'(^.*$)',r'\1'),))proxy_task=awaitstart()# ... Receive requests# Initiate stopping: new requests will not be processed...proxy_task.cancel()try:# ... and we wait until previously received requests have been processedawaitproxy_taskexceptasyncio.CancelledError:pass
优雅关机示例
下面是对SIGINT或SIGTERM执行正常关闭的服务器的完整示例。在
importasyncioimportsignalfromdnsrewriteproxyimport(DnsProxy,)asyncdefasync_main():start=DnsProxy(rules=((r'(^.*$)',r'\1'),))proxy_task=awaitstart()loop=asyncio.get_running_loop()loop.add_signal_handler(signal.SIGINT,proxy_task.cancel)loop.add_signal_handler(signal.SIGTERM,proxy_task.cancel)try:awaitproxy_taskexceptasyncio.CancelledError:passasyncio.run(async_main())print('End of program')
- 项目
标签: