feat: clear file

This commit is contained in:
sangge 2023-10-12 14:52:31 +08:00
parent 68247a7b1d
commit 27296aa76b
12 changed files with 0 additions and 549 deletions

View File

View File

@ -1,24 +0,0 @@
import dns.resolver
def resolver(domain):
# 构造 DNS 查询请求
qtype = 'A'
# 发送 DNS 查询请求
resolver = dns.resolver.Resolver()
resolver.nameservers = ["127.0.0.1"]
try:
ip = resolver.resolve(domain, qtype)[0]
return ip
except dns.resolver.NXDOMAIN:
print("can't find IP")
if __name__ == "__main__":
domain = 'mamahaha.work'
ip = resolver(domain)
print(ip)

View File

@ -1,66 +0,0 @@
from cryptography.hazmat.primitives.asymmetric import rsa, padding
from cryptography.hazmat.primitives import serialization, hashes
import base64
import random
# 生产随机域名
def generate_domain() -> str:
domain = random.getrandbits(64)
domain = hex(domain)[2:]
return domain + ".xiaomian"
def generate_key():
# Generate a new RSA key pair
private_key = rsa.generate_private_key(
public_exponent=65537,
key_size=2048
)
public_key = private_key.public_key()
# Convert keys to bytes
private_key_bytes = private_key.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.PKCS8,
encryption_algorithm=serialization.NoEncryption()
)
public_key_bytes = public_key.public_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PublicFormat.SubjectPublicKeyInfo
)
# Encode bytes as base64
private_key_base64 = base64.b64encode(private_key_bytes).decode('utf-8')
public_key_base64 = base64.b64encode(public_key_bytes).decode('utf-8')
return private_key_base64, public_key_base64
# # Encrypt a message using the public key
# message = b"Hello World"
# encrypted_message = public_key.encrypt(
# message,
# padding.OAEP(
# mgf=padding.MGF1(algorithm=hashes.SHA256()),
# algorithm=hashes.SHA256(),
# label=None
# )
# )
# # Decrypt the message using the private key
# decrypted_message = private_key.decrypt(
# encrypted_message,
# padding.OAEP(
# mgf=padding.MGF1(algorithm=hashes.SHA256()),
# algorithm=hashes.SHA256(),
# label=None
# )
# )
# print(decrypted_message)
if __name__ == '__main__':
print("Welcome to my xiaomiao tor network")
domain = generate_domain()
private_key_base64, public_key_base64 = generate_key()

Binary file not shown.

View File

@ -1,15 +0,0 @@
import sqlite3
db_file = 'database/dns.db'
if __name__ == '__main__':
conn = sqlite3.connect(db_file)
cursor = conn.cursor()
try:
cursor.execute(
'''CREATE TABLE xiaomiandns(domain TEXT PRIMARY KEY, ip TEXT, pubkey TEXT, nodetype TEXT,timestamp DATETIME)''')
# node type contain 3 types: client, node, server
except sqlite3.OperationalError:
print("table xiaomiandns already exists")
conn.commit()
cursor.close()
conn.close()

View File

@ -1,23 +0,0 @@
import sqlite3
db_file = 'database/dns.db'
if __name__ == '__main__':
conn = sqlite3.connect(db_file)
cursor = conn.cursor()
domain = 'mamahaha.wor12'
ip = "1.1.1.11"
pubkey = "asdfasdfadfsdf"
cursor.execute("SELECT * FROM xiaomiandns WHERE domain = ? OR ip = ? OR pubkey = ?",
(domain, ip, pubkey))
existing_data = cursor.fetchall()
if existing_data:
print("qqqqqq")
else:
# Insert the new data
cursor.execute(
"INSERT INTO xiaomiandns (domain, ip, pubkey) VALUES (?, ?, ?)", (domain, ip, pubkey))
print("Data inserted successfully")
conn.commit()
cursor.close()
conn.close()

View File

@ -1,2 +0,0 @@
import yaml

View File

View File

@ -1,55 +0,0 @@
import socket
import socketserver
import struct
import select
class ThreadingTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
pass
class Socks5Handler(socketserver.BaseRequestHandler):
VERSION = 5
def handle(self):
# 客户端发送版本和方法
version, nmethods = struct.unpack('!BB', self.request.recv(2))
self.request.recv(nmethods)
# 发送版本和方法响应
self.request.sendall(struct.pack('!BB', self.VERSION, 0))
# 获取请求详情
version, cmd, _, address_type = struct.unpack('!BBBB', self.request.recv(4))
if address_type == 1: # IPv4
address = socket.inet_ntoa(self.request.recv(4))
else:
raise NotImplementedError('Only IPv4 is supported.')
port = struct.unpack('!H', self.request.recv(2))[0]
# 发送响应
self.request.sendall(struct.pack('!BBBBIH', self.VERSION, 0, 0, 1,
int(socket.inet_aton('0.0.0.0').hex(), 16), 0))
# 建立连接
if cmd == 1: # CONNECT
remote = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
remote.connect((address, port))
self.exchange_loop(self.request, remote)
else:
raise NotImplementedError('Only CONNECT is supported.')
def exchange_loop(self, client, remote):
while True:
# Simple data exchange between client and remote
rlist, _, _ = select.select([client, remote], [], [])
if client in rlist:
data = client.recv(4096)
if remote.send(data) <= 0:
break
if remote in rlist:
data = remote.recv(4096)
if client.send(data) <= 0:
break
if __name__ == '__main__':
with ThreadingTCPServer(('0.0.0.0', 1080), Socks5Handler) as server:
server.serve_forever()

View File

@ -1,15 +0,0 @@
import xiaomiandns
import yaml
if __name__ == '__main__':
with open('serverconf.yaml', 'r') as f:
config = yaml.safe_load(f)
db_file = config['database']['db_file']
DNS_port = config['DNS']['port']
DNS_listen_host = config['DNS']['listen_host']
API_port = config['API']['port']
API_listen_host = config['API']['listen_host']
DNSServer = xiaomiandns.DNSServer(DNS_listen_host, DNS_port, db_file)
DNSServer.run()

View File

@ -1,8 +0,0 @@
database:
db_file : '../database/dns.db'
DNS:
port : 53
listen_host : "0.0.0.0"
API:
port : 81
listen_host : "0.0.0.0"

View File

@ -1,341 +0,0 @@
import socket
import threading
import dns.resolver
import dns.message
import dns.rdataclass
import dns.rdatatype
import dns.flags
import dns.rcode
import dns.rrset
import time
import sqlite3
import re
import base64
from cryptography.hazmat.primitives.asymmetric import rsa, padding
from cryptography.hazmat.primitives import serialization, hashes
class DNSServer:
def __init__(self, hostname, port, db_file):
self.hostname = hostname
self.port = port
self.db_file = db_file
def run(self):
self.udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.udp_socket.bind((self.hostname, self.port))
self.tcp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.tcp_socket.bind((self.hostname, self.port))
self.tcp_socket.listen(1)
print(f"DNS server running on {self.hostname}:{self.port}")
for i in range(3):
udp_thread = threading.Thread(target=self.handle_udp_request)
udp_thread.start()
tcp_thread = threading.Thread(target=self.handle_tcp_request)
tcp_thread.start()
def handle_udp_request(self):
data, address = self.udp_socket.recvfrom(1024)
response = self.handle_request(data)
self.udp_socket.sendto(response, address)
udp_thread = threading.Thread(target=self.handle_udp_request)
udp_thread.start()
def handle_tcp_request(self):
connection, address = self.tcp_socket.accept()
data = connection.recv(1024)
response = self.handle_request(data)
connection.send(response)
connection.close()
tcp_thread = threading.Thread(target=self.handle_tcp_request)
tcp_thread.start()
def handle_request(self, data):
conn = sqlite3.connect(self.db_file)
cur = conn.cursor()
question = dns.message.from_wire(data)
response = self.build_response(question, cur)
return response
def build_response(self, question, dbcursor, rcode=dns.rcode.NOERROR, answer=None):
# Create a new DNS message object
response = dns.message.Message()
# Set the message header fields
response.id = question.id
response.flags = dns.flags.QR | dns.flags.RA
# Add the question to the message
response.question = question.question
name = question.question[0].name
# search domain in database
dbcursor.execute(
"SELECT ip FROM xiaomiandns WHERE domain = ? AND nodetype = client", (str(name)[:-1],))
result = dbcursor.fetchone()
# Create a new RRset for the answer
if result is not None:
answer = dns.rrset.RRset(name, dns.rdataclass.IN, dns.rdatatype.A)
rdata = dns.rdata.from_text(
dns.rdataclass.IN, dns.rdatatype.A, result[0])
answer.add(rdata)
response.answer.append(answer)
# Set the response code
response.set_rcode(rcode)
else:
response.set_rcode(dns.rcode.NXDOMAIN)
return response.to_wire()
class DNSAPI:
# usage: use POST method
# /add
# data: domian=xxxx&ip=xx.xx.xx.xx&pubkey=xxxxx&nodetype=xxxx
# /delete
# data: domian=xxxx&ip=xx.xx.xx.xx&prikey=xxxxx&nodetype=xxxx
def __init__(self, hostname, port, db_file):
self.hostname = hostname
self.port = port
self.db_file = db_file
def run(self):
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 绑定 IP 地址和端口号
server_socket.bind((self.hostname, self.port))
# 监听连接
server_socket.listen(5)
print(f"API server running on {self.hostname}:{self.port}")
while True:
# 接受连接
conn, addr = server_socket.accept()
# 处理请求
t = threading.Thread(target=self.handle_tcp_request, args=(conn,))
t.start()
def handle_tcp_request(self, conn):
request = conn.recv(1024).decode('utf-8')
response = self.handle_http_request(request)
conn.send(response)
conn.close()
def handle_http_request(self, request):
request_line, headers = request.split('\r\n\r\n', 2)
method, url, version = request_line.split(' ', 2)
if method == 'GET':
response = self.handle_get_request(url)
elif method == 'POST':
data = request.split('\r\n')[-1]
response = self.handle_post_request(url, data)
else:
response = self.handle_error_request()
return response
def handle_get_request(self, url):
# check url start with /add
# if re.match(r'^/add\?', url):
# status_code = self.add_data(url[5:])
# if status_code == 200:
# reason_phrase = 'Add data successful'
# else:
# reason_phrase = 'Add data unsuccessful'
# # check url start with /delete
# elif re.match(r'^/delete\?', url):
# status_code = self.delete_data(url[9:])
# if status_code == 200:
# reason_phrase = 'Delete data successful'
# else:
# reason_phrase = 'Delete data unsuccessful'
# else:
# status_code = 400
# reason_phrase = 'unsupport api'
response = 'HTTP/1.1 {} {}\r\n'.format(status_code, reason_phrase)
return response.encode("utf-8")
def handle_post_request(self, url, data):
# 处理 POST 请求data 是 POST 方法提交的数据
# check url start with /add
if re.match(r'^/add\?', url):
status_code = self.add_data(data)
if status_code == 200:
reason_phrase = 'Add data successful'
else:
reason_phrase = 'Add data unsuccessful'
# check url start with /delete
elif re.match(r'^/delete\?', url):
status_code = self.delete_data(data)
if status_code == 200:
reason_phrase = 'Delete data successful'
else:
reason_phrase = 'Delete data unsuccessful'
else:
status_code = 400
reason_phrase = 'unsupport api'
response = 'HTTP/1.1 {} {}\r\n'.format(status_code, reason_phrase)
return response.encode("utf-8")
def handle_error_request(self, request):
status_code = 400
reason_phrase = "unsupport method"
headers = {
'Content-Type': 'text/html',
'Connection': 'close',
}
response = 'HTTP/1.1 {} {}\r\n'.format(status_code, reason_phrase)
return response.encode("utf-8")
def add_data(self, data):
# parse and check validation
domain, ip, pubkey, nodetype = self.parse_data(data)
if not self.check_data(domain,ip,nodetype):
return 400
# connect db
conn = sqlite3.connect(self.db_file)
c = conn.cursor()
# Check if the data already exists
c.execute(
"SELECT * FROM xiaomiandns WHERE domain = ? OR ip = ? OR pubkey = ? OR nodetype = ?", (domain, ip, pubkey, nodetype))
existing_data = c.fetchall()
cursor.close()
conn.close()
if existing_data:
return 400
else:
# Insert the new data
c.execute(
"INSERT INTO xiaomiandns (domain,ip,pubkey,nodetype,timestamp) VALUES (?,?,?,?,DATETIME('now'))", (domain, ip, pubkey, nodetype))
return 200
def delete_data(self, data):
# parse and check validation
domain, ip, private_key_base64, nodetype = self.parse_data(data)
if not self.check_data(domain, ip ,nodetype):
return 400
# connect db
conn = sqlite3.connect(self.db_file)
c = conn.cursor()
c.execute(
"SELECT pubkey FROM xiaomiandns WHERE domain = ? AND ip = ? AND nodetype = ?", (domain, ip, nodetype))
public_key_base64 = c.fetchone()
cursor.close()
conn.close()
if public_key_base64 != None:
public_key_base64 = public_key_base64[0]
else:
return 400
private_key_bytes = base64.b64decode(
private_key_base64).decode("utf-8")
private_key = serialization.load_pem_private_key(
private_key_bytes,
password=None
)
gen_public_key = private_key.public_key()
gen_public_key_bytes = gen_public_key.public_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PublicFormat.SubjectPublicKeyInfo
)
gen_public_key_base64 = base64.b64encode(gen_public_key_bytes).decode('utf-8')
if gen_public_key_base64 == public_key_base64:
conn = sqlite3.connect(self.db_file)
c = conn.cursor()
c.execute(
"DELETE FROM xiaomiandns WHERE domain = ? AND ip = ? AND nodetype = ?", (domain, ip, nodetype))
cursor.close()
conn.close()
return 200
else:
return 400
def parse_data(self, data):
domain = re.search(r'domain=([^&]+)', data)
ip = re.search(r'ip=([^&]+)', data)
pubkey = re.search(r'pubkey=([^&]+)', data)
privkey = re.search(r'privkey=([^&]+)', data)
nodetype = re.search(r'nodetype=([^]+)', data)
if domain and ip and nodetype:
domain = domain.group(1)
ip = ip.group(1)
nodetype = nodetype.group(1)
if bool(pubkey) != bool(privkey):
if pubkey:
key = pubkey.group(1)
else:
key = privkey.group(1)
return domain, ip, key, nodetype
def check_data(self, domain, ip, nodetype):
# check domain
pattern = r'^[a-z0-9]{16}\.xiaomian$'
if re.match(pattern, domain):
return True
else:
return False
# check ip
pattern = r'^(\d{1,3}\.){3}\d{1,3}$'
if re.match(pattern, ip):
octets = ip.split('.')
if all(int(octet) < 256 for octet in octets):
return True
return False
# check nodetype
if nodetype in {"server", "client", "node"}:
return True
else:
return False
if __name__ == '__main__':
with open('serverconf.yaml', 'r') as f:
config = yaml.safe_load(f)
db_file = config['database']['db_file']
DNS_port = config['DNS']['port']
DNS_listen_host = config['DNS']['listen_host']
API_port = config['API']['port']
API_listen_host = config['API']['listen_host']
# start dns server
server = DNSServer(API_listen_host, DNS_port, db_file)
server.run()
# start dns api server
APIserver = DNSAPI(API_listen_host, API_port, db_file)
APIserver.run()