V1.0
authorFedor Sevrugin <fedor.sevrugin@gmail.com>
Sun, 19 Jan 2025 03:08:21 +0000 (06:08 +0300)
committerFedor Sevrugin <fedor.sevrugin@gmail.com>
Sun, 19 Jan 2025 03:08:21 +0000 (06:08 +0300)
README.md
blacklist.txt [new file with mode: 0644]
fedordpi.py [new file with mode: 0644]

index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..baa02c67a84aba504f8a97c89e703817439c099e 100644 (file)
--- a/README.md
+++ b/README.md
@@ -0,0 +1,9 @@
+FedorDPI — это аналог GoodbyeDPI и прочих сервисов по обходу DPI. Но в оличии от других решений, этот был написан самостоятельно, исходный код открыт, а значит, его можно самостоятельно проверить на безовасность. FedorDPI представляет собой прокси сервер, который коверкает пакеты для сайтов указанных в файле blacklist.txt и оставляет без изменений остальные запросы.  
+
+После запуска: python3 fedordpi.py 
+
+Прокси сервер будет доступен по адресу: 127.0.0.1:8881
+
+Пропишите настройку прокси сервера в браузере и проверяйте работу ;)  
+  
+Известные проблемы: Не пропускает трафик по http протоколу, если ктото пофиксит будет круто.
diff --git a/blacklist.txt b/blacklist.txt
new file mode 100644 (file)
index 0000000..e2b528e
--- /dev/null
@@ -0,0 +1,14 @@
+youtube.com
+youtu.be
+yt.be
+googlevideo.com
+ytimg.com
+ggpht.com
+gvt1.com
+youtube-nocookie.com
+youtube-ui.l.google.com
+youtubeembeddedplayer.googleapis.com
+youtube.googleapis.com
+youtubei.googleapis.com
+yt-video-upload.l.google.com
+wide-youtube.l.google.com
diff --git a/fedordpi.py b/fedordpi.py
new file mode 100644 (file)
index 0000000..78feec0
--- /dev/null
@@ -0,0 +1,81 @@
+import random
+import asyncio
+
+BLOCKED = [line.rstrip().encode() for line in open('blacklist.txt', 'r', encoding='utf-8')]
+TASKS = []
+
+
+async def main(host, port):
+
+    server = await asyncio.start_server(new_conn, host, port)
+    await server.serve_forever()
+
+
+async def pipe(reader, writer):
+
+    while not reader.at_eof() and not writer.is_closing():
+        try:
+            writer.write(await reader.read(1500))
+            await writer.drain()
+        except:
+            break
+
+    writer.close()
+
+
+async def new_conn(local_reader, local_writer):
+
+    http_data = await local_reader.read(1500)
+    
+    try:
+        type, target = http_data.split(b"\r\n")[0].split(b" ")[0:2]
+        host, port = target.split(b":")
+    except:
+        local_writer.close()
+        return
+    
+    if (type != b"CONNECT"):
+        local_writer.close()
+        return
+    
+    local_writer.write(b'HTTP/1.1 200 OK\n\n')
+    await local_writer.drain()
+    
+    try:
+        remote_reader, remote_writer = await asyncio.open_connection(host, port)
+    except:
+        local_writer.close()
+        return
+    
+    if (port == b'443'):
+        await fragemtn_data(local_reader, remote_writer)
+    
+    TASKS.append(asyncio.create_task(pipe(local_reader, remote_writer)))
+    TASKS.append(asyncio.create_task(pipe(remote_reader, local_writer)))
+
+
+async def fragemtn_data(local_reader, remote_writer):
+
+    head = await local_reader.read(5)
+    data = await local_reader.read(1500)
+    parts = []
+
+    if all([data.find(site) == -1 for site in BLOCKED]):
+        remote_writer.write(head + data)
+        await remote_writer.drain()
+        
+        return
+
+    while data:
+        part_len = random.randint(1, len(data))
+        parts.append(bytes.fromhex("1603") + bytes([random.randint(0, 255)]) + int(
+            part_len).to_bytes(2, byteorder='big') + data[0:part_len])
+
+        data = data[part_len:]
+    
+    remote_writer.write(b''.join(parts))
+    await remote_writer.drain()
+
+
+asyncio.run(main(host='127.0.0.1', port=8881))
+