有条件地重写和过滤记录请求的DNS代理服务器

dnsrewriteprox的Python项目详细描述


dns重写代理CircleCITest Coverage

有条件地重写和过滤记录请求的DNS代理服务器。用Python编写,所有代码都在一个模块中,并且有一个单独的依赖项aiodnsresolver。在

CNAME由代理跟踪并解析为IP地址,并且从不返回给客户端。在

安装

pip install dnsrewriteproxy

使用

默认情况下,代理将监听端口53,并向/etc/resolv.conf中的服务器发出代理请求。但是,默认情况下,所有请求都被阻止,没有显式规则,因此要代理请求,必须至少配置一个重写规则。在

^{pr2}$

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')

欢迎加入QQ群-->: 979659372 Python中文网_新手群

推荐PyPI第三方库


热门话题
java不兼容类型:MainActivity无法转换为LifecycleOwner   java安卓是一种更有效的读取大文本文件的方法   java导出LWJGL本地人与项目?(IntelliJ IDEA)   JDK更新后,JavaJShell不再在下一行打印输出   父类对象上的继承Java比较子属性   Java:有没有一个容器可以有效地结合HashMap和ArrayList?   安卓 Java对象指针   java在annotationdriven Spring MVC应用程序中实现大气   java 安卓源代码构建应用找不到安卓supportv4。罐子   文件系统上的抽象层和Java中的jar/zip   java在水平滚动视图中添加多个图像?   java如何从firebase实时数据库中获取字符串数组   WIndows 10工作站上的java未满足链接错误   java命令在终端中工作,但在使用过程中出现“无结束引号”错误。执行官