diff --git a/.gitignore b/.gitignore
index 24e7908..200ff53 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,3 +2,4 @@ env
dist
build
gfw/DNS_IP_traffic_info.txt
+ffmpeg.exe
diff --git a/ffmpeg/note.txt b/ffmpeg/note.txt
new file mode 100644
index 0000000..3fa8375
--- /dev/null
+++ b/ffmpeg/note.txt
@@ -0,0 +1 @@
+add ffmpeg.exe here to build for windows
\ No newline at end of file
diff --git a/gfw/Android/README.md b/gfw/Android/README.md
deleted file mode 100644
index 5c9cbac..0000000
--- a/gfw/Android/README.md
+++ /dev/null
@@ -1,22 +0,0 @@
-# نحوه اجرا
-1. ابتدا کد پایتون را روی گوشی (یا کامپیوتر) اجرا کنید
-(ویدئو آموزشی از نحوه اجرای کد پایتون در گوشی های اندرویدی https://t.me/ircfspace/124)
-2. کانفیگ HTTP را روی nekobox یا matsuri بسازید مطابق شکل زیر
-
-
-اگر پایتون روی گوشی اجرا شده آدرس 127.0.0.1 و اگر روی کامپیوتر باشد ادرس ip کامپیوتر مثلا 192.168.1.2 را میدهید
-
-اگر روی vpn mode هستید باید ترافیک پایتون را از vpn مستثنی کنید
-
-3. در صورت تمایل میتوانید بجای ساخت کانفیگ ، فایل آماده json را import کنید (و بعد باید پایتون را از vpn مستثنی کنید)
-
-# رفع اشکال
-- برنامه v2rayNG روی گوشی از پروتکل HTTP پشتیبانی نمیکند بنابراین از nekobox یا matsuri استفاده کنید
-- اگر مشکل loading video دارید از نت ایرانسل استفاده کنید
-- از داخل کد ، num_fragment را میتوانید از 10 تا 100 یا حتی بیشتر به دلخواه تنظیم کنید
-- زمان fragment_sleep را از 0.001 تا 0.01 به دلخواه تنظیم کنید
-
-# آپدیت 30-2-1402
-- قسمت logging از کد حذف شد چون نیاز به دسترسی برای نوشتن فایل داشت و در برخی گوشی ها خطا میداد.
-- تمام print ها کامنت شد که پردازش روی گوشی ایجاد نکند
-- کانفیگ مخصوص nekobox و matsuri قرار داده شد
diff --git a/gfw/Android/matsuri_http_config.json b/gfw/Android/matsuri_http_config.json
deleted file mode 100644
index 8d627d8..0000000
--- a/gfw/Android/matsuri_http_config.json
+++ /dev/null
@@ -1,137 +0,0 @@
-{
- "dns": {
- "fallbackStrategy": "disabled_if_any_match",
- "hosts": {},
- "queryStrategy": "UseIPv4",
- "servers": [
- {
- "address": "https://8.8.8.8/dns-query",
- "domains": [],
- "uidList": []
- }
- ]
- },
- "inbounds": [
- {
- "listen": "127.0.0.1",
- "port": 2080,
- "protocol": "socks",
- "settings": {
- "auth": "noauth",
- "udp": true
- },
- "sniffing": {
- "destOverride": [
- "http",
- "tls",
- "quic"
- ],
- "enabled": true,
- "metadataOnly": false,
- "routeOnly": true
- },
- "tag": "socks"
- },
- {
- "listen": "127.0.0.1",
- "port": 9080,
- "protocol": "http",
- "settings": {
- "allowTransparent": true
- },
- "sniffing": {
- "destOverride": [
- "http",
- "tls"
- ],
- "enabled": true,
- "metadataOnly": false,
- "routeOnly": true
- },
- "tag": "http"
- },
- {
- "listen": "127.0.0.1",
- "port": 6450,
- "protocol": "dokodemo-door",
- "settings": {
- "address": "8.8.8.8",
- "network": "tcp,udp",
- "port": 53
- },
- "tag": "dns-in"
- }
- ],
- "log": {
- "loglevel": "error"
- },
- "outbounds": [
- {
- "domainStrategy": "AsIs",
- "protocol": "http",
- "settings": {
- "servers": [
- {
- "address": "127.0.0.1",
- "port": 4500
- }
- ]
- },
- "streamSettings": {
- "network": "tcp",
- "tcpSettings": {}
- },
- "tag": "proxy"
- },
- {
- "protocol": "freedom",
- "tag": "direct"
- },
- {
- "protocol": "freedom",
- "tag": "bypass"
- },
- {
- "protocol": "blackhole",
- "tag": "block"
- },
- {
- "protocol": "dns",
- "settings": {
- "userLevel": 1
- },
- "tag": "dns-out"
- }
- ],
- "policy": {
- "levels": {
- "1": {
- "connIdle": 30
- }
- },
- "system": {
- "statsOutboundDownlink": true,
- "statsOutboundUplink": true
- }
- },
- "routing": {
- "domainStrategy": "AsIs",
- "rules": [
- {
- "inboundTag": [
- "dns-in"
- ],
- "outboundTag": "dns-out",
- "type": "field"
- },
- {
- "ip": [
- "geoip:private"
- ],
- "outboundTag": "bypass",
- "type": "field"
- }
- ]
- },
- "stats": {}
-}
\ No newline at end of file
diff --git a/gfw/Android/neko_http_config.json b/gfw/Android/neko_http_config.json
deleted file mode 100644
index f262944..0000000
--- a/gfw/Android/neko_http_config.json
+++ /dev/null
@@ -1,142 +0,0 @@
-{
- "dns": {
- "rules": [
- {
- "auth_user": [
- "fakedns"
- ],
- "server": "dns-remote"
- },
- {
- "disable_cache": true,
- "domain_suffix": [
- ".arpa.",
- ".arpa"
- ],
- "server": "dns-block"
- },
- {
- "disable_cache": true,
- "inbound": [
- "tun-in"
- ],
- "server": "dns-fake"
- }
- ],
- "servers": [
- {
- "address": "https://8.8.8.8/dns-query",
- "address_resolver": "dns-direct",
- "tag": "dns-remote"
- },
- {
- "address": "https://223.5.5.5/dns-query",
- "address_resolver": "dns-local",
- "detour": "direct",
- "tag": "dns-direct"
- },
- {
- "address": "underlying://0.0.0.0",
- "detour": "direct",
- "tag": "dns-local"
- },
- {
- "address": "rcode://success",
- "tag": "dns-block"
- },
- {
- "address": "fakedns://198.18.0.0/15",
- "strategy": "ipv4_only",
- "tag": "dns-fake"
- }
- ],
- "strategy": "ipv4_only"
- },
- "inbounds": [
- {
- "listen": "127.0.0.1",
- "listen_port": 6450,
- "override_address": "8.8.8.8",
- "override_port": 53,
- "tag": "dns-in",
- "type": "direct"
- },
- {
- "domain_strategy": "",
- "endpoint_independent_nat": true,
- "inet4_address": [
- "172.19.0.1/28"
- ],
- "sniff": true,
- "stack": "system",
- "tag": "tun-in",
- "type": "tun"
- },
- {
- "domain_strategy": "",
- "listen": "127.0.0.1",
- "listen_port": 2080,
- "sniff": true,
- "tag": "mixed-in",
- "type": "mixed"
- }
- ],
- "log": {
- "level": "panic"
- },
- "outbounds": [
- {
- "password": "",
- "server": "127.0.0.1",
- "server_port": 4500,
- "username": "",
- "type": "http",
- "tag": "proxy",
- "domain_strategy": ""
- },
- {
- "tag": "direct",
- "type": "direct"
- },
- {
- "tag": "bypass",
- "type": "direct"
- },
- {
- "tag": "block",
- "type": "block"
- },
- {
- "tag": "dns-out",
- "type": "dns"
- }
- ],
- "route": {
- "auto_detect_interface": true,
- "rules": [
- {
- "outbound": "dns-out",
- "port": [
- 53
- ]
- },
- {
- "inbound": [
- "dns-in"
- ],
- "outbound": "dns-out"
- },
- {
- "ip_cidr": [
- "224.0.0.0/3",
- "ff00::/8"
- ],
- "outbound": "block",
- "source_ip_cidr": [
- "224.0.0.0/3",
- "ff00::/8"
- ]
- }
- ]
- }
-}
\ No newline at end of file
diff --git a/gfw/Android/pyprox_HTTPS_v1.0.py b/gfw/Android/pyprox_HTTPS_v1.0.py
deleted file mode 100644
index 5d23542..0000000
--- a/gfw/Android/pyprox_HTTPS_v1.0.py
+++ /dev/null
@@ -1,503 +0,0 @@
-#!/usr/bin/env python3
-
-import dns.message # --> pip install dnspython
-import dns.rdatatype
-import requests # --> pip install requests
-from pathlib import Path
-import os
-import base64
-import socket
-import threading
-import time
-import random
-
-
-
-
-listen_PORT = 4500 # pyprox listening to 127.0.0.1:listen_PORT
-
-num_fragment = 87 # total number of chunks that ClientHello devided into (chunks with random size)
-fragment_sleep = 0.001 # sleep between each fragment to make GFW-cache full so it forget previous chunks. LOL.
-
-log_every_N_sec = 10 # every 30 second , update log file with latest DNS-cache statistics
-
-# DNS_url = 'https://cloudflare-dns.com/dns-query?dns=' # not working in iran , ip blocked
-# DNS_url = 'https://dns.google/dns-query?dns=' # not working in iran , ip blocked
-# DNS_url = 'https://doh.opendns.com/dns-query?dns=' # not working in iran , ip blocked
-# DNS_url = 'https://secure.avastdns.com/dns-query?dns=' # not working in iran , ip blocked
-# DNS_url = 'https://doh.libredns.gr/dns-query?dns=' # not working in iran , ip blocked
-DNS_url = 'https://dns.electrotm.org/dns-query?dns='
-# DNS_url = 'https://dns.bitdefender.net/dns-query?dns='
-# DNS_url = 'https://cluster-1.gac.edu/dns-query?dns='
-
-
-
-
-offline_DNS = {
-
-
-
-# ################# twitter working pack ###################
-'ocsp.digicert.com': '192.229.211.108',
-
-'api.twitter.com': '104.244.42.66',
-'twitter.com': '104.244.42.1',
-'pbs.twimg.com': '93.184.220.70',
-'abs-0.twimg.com': '104.244.43.131',
-'abs.twimg.com': '152.199.24.185',
-'video.twimg.com': '192.229.220.133',
-'t.co': '104.244.42.69',
-'ton.local.twitter.com':'104.244.42.1',
-# ##########################################################
-
-
-
-##################### Google working pack ###################
-'ocsp.pki.goog': '172.217.16.195',
-'googleads.g.doubleclick.net': '45.157.177.108',
-'fonts.gstatic.com': '142.250.185.227',
-'rr2---sn-vh5ouxa-hju6.googlevideo.com': '213.202.6.141',
-'jnn-pa.googleapis.com': '45.157.177.108',
-'static.doubleclick.net': '202.61.195.218',
-'rr4---sn-hju7en7k.googlevideo.com': '74.125.167.74',
-'rr1---sn-hju7en7r.googlevideo.com': '74.125.167.87',
-'play.google.com': '142.250.184.238',
-'rr3---sn-vh5ouxa-hjuz.googlevideo.com': '134.0.218.206',
-'rr3---sn-hju7enel.googlevideo.com': '74.125.98.40',
-'download.visualstudio.microsoft.com': '68.232.34.200',
-'ocsp.pki.goog': '172.217.16.195',
-'i.ytimg.com': '142.250.186.150',
-'rr2---sn-hju7enel.googlevideo.com': '74.125.98.39',
-'rr2---sn-hju7en7k.googlevideo.com': '74.125.167.72',
-'googleads.g.doubleclick.net': '45.157.177.108',
-'rr3---sn-4g5lznl6.googlevideo.com': '74.125.173.40',
-'jnn-pa.googleapis.com': '89.58.57.45',
-'rr3---sn-hju7en7k.googlevideo.com': '74.125.167.73',
-'rr1---sn-hju7enll.googlevideo.com': '74.125.98.6',
-'rr6---sn-hju7en7r.googlevideo.com': '74.125.167.92',
-'play.google.com': '216.58.212.174',
-'www.gstatic.com': '142.250.185.99',
-'apis.google.com': '172.217.23.110',
-'adservice.google.com': '202.61.195.218',
-'mail.google.com': '142.250.186.37',
-'accounts.google.com': '172.217.16.205',
-
-# 'lh3.googleusercontent.com': '193.26.157.66', # filtered
-'lh3.googleusercontent.com':'142.251.167.132',
-
-'accounts.youtube.com': '172.217.16.206',
-'ssl.gstatic.com': '142.250.184.195',
-'fonts.gstatic.com': '172.217.23.99',
-'rr4---sn-hju7enll.googlevideo.com': '74.125.98.9', # good
-'rr2---sn-hju7enll.googlevideo.com': '74.125.98.7',
-'rr1---sn-hju7enel.googlevideo.com': '74.125.98.38',
-'rr5---sn-vh5ouxa-hjuz.googlevideo.com': '134.0.218.208',
-'i1.ytimg.com': '172.217.18.14',
-'plos.org': '162.159.135.42',
-'fonts.googleapis.com': '89.58.57.45',
-'genweb.plos.org': '104.26.1.141',
-'static.ads-twitter.com': '146.75.120.157',
-'www.google-analytics.com': '142.250.185.174',
-'rr1---sn-vh5ouxa-hju6.googlevideo.com': '213.202.6.140',
-'rr5---sn-vh5ouxa-hju6.googlevideo.com': '213.202.6.144',
-'rr3---sn-hju7enel.googlevideo.com': '74.125.98.40',
-'rr5---sn-nv47zn7y.googlevideo.com': '173.194.15.74',
-'safebrowsing.googleapis.com': '202.61.195.218',
-'static.doubleclick.net': '193.26.157.66',
-'rr5---sn-vh5ouxa-hju6.googlevideo.com': '213.202.6.144',
-'rr1---sn-hju7en7r.googlevideo.com': '74.125.167.87',
-'rr4---sn-vh5ouxa-hju6.googlevideo.com': '213.202.6.143',
-'rr4---sn-hju7en7r.googlevideo.com': '74.125.167.90',
-'r1---sn-hju7enel.googlevideo.com': '74.125.98.38',
-'rr1---sn-nv47zn7r.googlevideo.com': '173.194.15.38',
-'rr2---sn-vh5ouxa-hjuz.googlevideo.com': '134.0.218.205',
-'rr4---sn-nv47zn7r.googlevideo.com': '173.194.15.41',
-'rr4---sn-hju7en7r.googlevideo.com': '74.125.167.90',
-
-
-'rr4---sn-nv47znel.googlevideo.com': '74.125.98.7', # good
-'rr4---sn-nv47lnl7.googlevideo.com':'74.125.98.7',
-'rr4---sn-hju7enll.googlevideo.com':'74.125.98.7',
-'rr1---sn-vh5ouxa-hju6.googlevideo.com':'74.125.98.7',
-'rr3---sn-hju7enel.googlevideo.com':'74.125.98.7',
-'rr5---sn-hju7enll.googlevideo.com':'74.125.98.7',
-'rr5---sn-vh5ouxa-hjuz.googlevideo.com':'74.125.98.7',
-'rr1---sn-nv47ln7z.googlevideo.com':'74.125.98.7',
-'rr3---sn-vh5ouxa-hju6.googlevideo.com': '74.125.98.7',
-
-
-'www.google.com': '142.250.186.36',
-# 'www.google.com': '216.239.38.120',
-'youtube.com':'216.239.38.120',
-'www.youtube.com':'216.239.38.120',
-'i.ytimg.com':'216.239.38.120',
-
-# 'yt3.ggpht.com': '64.233.165.198', # filtered
-# 'yt3.ggpht.com': '142.250.179.161', # filtered
-# 'yt3.ggpht.com': '142.250.186.65', # sometimes work
-'yt3.ggpht.com': '142.250.186.36', # most of times work
-#######################################################
-
-
-################## DNS over HTTPS IP Address (leave it intact , it must Exist) ######################
-'cloudflare-dns.com':'1.1.1.1', # not working in iran , ip blocked
-'dns.google':'8.8.8.8', # not working in iran , ip blocked
-'doh.opendns.com':'208.67.222.222', # not working in iran , ip blocked
-'secure.avastdns.com':'185.185.133.66', # not working in iran , ip blocked
-'doh.libredns.gr':'116.202.176.26', # not working in iran , ip blocked
-'dns.electrotm.org':'78.157.42.100',
-'dns.bitdefender.net':'34.84.232.67',
-'cluster-1.gac.edu':'138.236.128.101',
-##########################################################################
-
-}
-
-
-
-
-
-
-
-
-# ignore description below , its for old code , just leave it intact.
-my_socket_timeout = 21 # default for google is ~21 sec , recommend 60 sec unless you have low ram and need close soon
-first_time_sleep = 0.1 # speed control , avoid server crash if huge number of users flooding
-accept_time_sleep = 0.01 # avoid server crash on flooding request -> max 100 sockets per second
-
-
-DNS_cache = {} # resolved domains
-IP_DL_traffic = {} # download usage for each ip
-IP_UL_traffic = {} # upload usage for each ip
-
-
-class DNS_over_Fragment:
- def __init__(self):
- self.url = DNS_url
- self.req = requests.session()
- self.fragment_proxy = {
- 'https': 'http://127.0.0.1:'+str(listen_PORT)
- }
-
-
-
- def query(self,server_name):
-
- offline_ip = offline_DNS.get(server_name,None)
- if(offline_ip!=None):
- # print('offline DNS -->',server_name,offline_ip)
- return offline_ip
-
- cache_ip = DNS_cache.get(server_name,None)
- if(cache_ip!=None):
- # print('cached DNS -->',server_name,cache_ip)
- return cache_ip
-
- quary_params = {
- # 'name': server_name, # no need for this when using dns wire-format , cause 400 err on some server
- 'type': 'A',
- 'ct': 'application/dns-message',
- }
-
-
- # print(f'online DNS Query',server_name)
- try:
- query_message = dns.message.make_query(server_name,'A')
- query_wire = query_message.to_wire()
- query_base64 = base64.urlsafe_b64encode(query_wire).decode('utf-8')
- query_base64 = query_base64.replace('=','') # remove base64 padding to append in url
-
- query_url = self.url + query_base64
- ans = self.req.get( query_url , params=quary_params , headers={'accept': 'application/dns-message'} , proxies=self.fragment_proxy)
-
- # Parse the response as a DNS packet
- if ans.status_code == 200 and ans.headers.get('content-type') == 'application/dns-message':
- answer_msg = dns.message.from_wire(ans.content)
-
- resolved_ip = None
- for x in answer_msg.answer:
- if (x.rdtype == dns.rdatatype.A):
- resolved_ip = x[0].address # pick first ip in DNS answer
- DNS_cache[server_name] = resolved_ip
- # print("################# DNS Cache is : ####################")
- # print(DNS_cache) # print DNS cache , it usefull to track all resolved IPs , to be used later.
- # print("#####################################################")
- break
-
- # print(f'online DNS --> Resolved {server_name} to {resolved_ip}')
- return resolved_ip
- else:
- print(f'Error: {ans.status_code} {ans.reason}')
- except Exception as e:
- print(repr(e))
-
-
-
-
-
-
-
-
-
-class ThreadedServer(object):
- def __init__(self, host, port):
- self.DoH = DNS_over_Fragment()
- self.host = host
- self.port = port
- self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
- self.sock.bind((self.host, self.port))
-
- def listen(self):
- self.sock.listen(128) # up to 128 concurrent unaccepted socket queued , the more is refused untill accepting those.
-
- while True:
- client_sock , client_addr = self.sock.accept()
- client_sock.settimeout(my_socket_timeout)
-
- time.sleep(accept_time_sleep) # avoid server crash on flooding request
- thread_up = threading.Thread(target = self.my_upstream , args =(client_sock,) )
- thread_up.daemon = True #avoid memory leak by telling os its belong to main program , its not a separate program , so gc collect it when thread finish
- thread_up.start()
-
-
-
- def handle_client_request(self,client_socket):
- # Receive the CONNECT request from the client
- data = client_socket.recv(16384)
-
-
- if(data[:7]==b'CONNECT'):
- server_name , server_port = self.extract_servername_and_port(data)
- elif( (data[:3]==b'GET') or (data[:4]==b'POST')):
- q_line = str(data).split('\r\n')
- q_url = q_line[0].split()[1]
- q_url = q_url.replace('http://','https://')
- # print('redirect http to HTTPS',q_url)
- response_data = 'HTTP/1.1 302 Found\r\nLocation: '+q_url+'\r\nProxy-agent: MyProxy/1.0\r\n\r\n'
- client_socket.sendall(response_data.encode())
- client_socket.close()
- return None
- else:
- # print('Unknown Method',str(data[:10]))
- response_data = b'HTTP/1.1 400 Bad Request\r\nProxy-agent: MyProxy/1.0\r\n\r\n'
- client_socket.sendall(response_data)
- client_socket.close()
- return None
-
-
- # print(server_name,'-->',server_port)
-
- try:
- server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- server_socket.settimeout(my_socket_timeout)
- server_socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) #force localhost kernel to send TCP packet immediately (idea: @free_the_internet)
-
- try:
- socket.inet_aton(server_name)
- # print('legal IP')
- server_IP = server_name
- except socket.error:
- # print('Not IP , its domain , try to resolve it')
- server_IP = self.DoH.query(server_name)
-
- server_socket.connect((server_IP, server_port))
- # Send HTTP 200 OK
- response_data = b'HTTP/1.1 200 Connection established\r\nProxy-agent: MyProxy/1.0\r\n\r\n'
- client_socket.sendall(response_data)
- return server_socket
- except Exception as e:
- print(repr(e))
- # Send HTTP ERR 502
- response_data = b'HTTP/1.1 502 Bad Gateway\r\nProxy-agent: MyProxy/1.0\r\n\r\n'
- client_socket.sendall(response_data)
- client_socket.close()
- server_socket.close()
- return None
-
-
-
-
-
-
-
- def my_upstream(self, client_sock):
- first_flag = True
- backend_sock = self.handle_client_request(client_sock)
-
- if(backend_sock==None):
- client_sock.close()
- return False
-
- this_ip = backend_sock.getpeername()[0]
- if(this_ip not in IP_UL_traffic):
- IP_UL_traffic[this_ip] = 0
-
-
- while True:
- try:
- if( first_flag == True ):
- first_flag = False
-
- time.sleep(first_time_sleep) # speed control + waiting for packet to fully recieve
- data = client_sock.recv(16384)
- #print('len data -> ',str(len(data)))
- #print('user talk :')
-
- if data:
- thread_down = threading.Thread(target = self.my_downstream , args = (backend_sock , client_sock) )
- thread_down.daemon = True
- thread_down.start()
- # backend_sock.sendall(data)
- send_data_in_fragment(data,backend_sock)
- IP_UL_traffic[this_ip] = IP_UL_traffic[this_ip] + len(data)
-
- else:
- raise Exception('cli syn close')
-
- else:
- data = client_sock.recv(16384)
- if data:
- backend_sock.sendall(data)
- IP_UL_traffic[this_ip] = IP_UL_traffic[this_ip] + len(data)
- else:
- raise Exception('cli pipe close')
-
- except Exception as e:
- #print('upstream : '+ repr(e) )
- time.sleep(2) # wait two second for another thread to flush
- client_sock.close()
- backend_sock.close()
- return False
-
-
-
-
- def my_downstream(self, backend_sock , client_sock):
- this_ip = backend_sock.getpeername()[0]
- if(this_ip not in IP_DL_traffic):
- IP_DL_traffic[this_ip] = 0
-
-
- first_flag = True
- while True:
- try:
- if( first_flag == True ):
- first_flag = False
- data = backend_sock.recv(16384)
- if data:
- client_sock.sendall(data)
- IP_DL_traffic[this_ip] = IP_DL_traffic[this_ip] + len(data)
- else:
- raise Exception('backend pipe close at first')
-
- else:
- data = backend_sock.recv(16384)
- if data:
- client_sock.sendall(data)
- IP_DL_traffic[this_ip] = IP_DL_traffic[this_ip] + len(data)
- else:
- raise Exception('backend pipe close')
-
- except Exception as e:
- #print('downstream '+backend_name +' : '+ repr(e))
- time.sleep(2) # wait two second for another thread to flush
- backend_sock.close()
- client_sock.close()
- return False
-
-
-
- def extract_servername_and_port(self,data):
- host_and_port = str(data).split()[1]
- host,port = host_and_port.split(':')
- return (host,int(port))
-
-
-
-def merge_all_dicts():
- full_DNS = {**DNS_cache, **offline_DNS} # merge two dict , need python 3.5 or up
- inv_DNS = { v:k for k, v in full_DNS.items()} # inverse mapping to look for domain given ip
- stats = {}
- for ip in IP_DL_traffic:
- up = round(IP_UL_traffic[ip]/(1024.0),3)
- down = round(IP_DL_traffic[ip]/(1024.0),3)
- host = inv_DNS.get(ip,'?')
- if((up>down) and (down<1.0)): # download below 1KB
- maybe_filter = 'maybe'
- else:
- maybe_filter = '-------'
-
- su = f'UL={up} KB:'
- sd = f'DL={down} KB:'
- sf = f'filtered={maybe_filter}:'
- sh = f'Host={host}:'
- stats[ip] = ':'+su+sd+sf+sh
- return stats
-
-
-
-# only run in separate thread
-def log_writer():
- file_name = 'DNS_IP_traffic_info.txt'
- BASE_DIR = Path(__file__).resolve().parent
- log_file_path = os.path.join(BASE_DIR,file_name)
-
- with open(log_file_path, "w") as f:
- while True:
- time.sleep(log_every_N_sec)
- all_stats_info = merge_all_dicts()
- f.seek(0)
- f.write('\n########### new DNS resolved : ##############\n')
- f.write(str(DNS_cache).replace(',',',\n'))
- f.write('\n#############################################\n')
- f.write('\n########### ALL INFO : ######################\n')
- f.write(str(all_stats_info).replace('\'','').replace(',','\n').replace(':','\t'))
- f.write('\n#############################################\n')
- f.flush()
- f.truncate()
- print("info file writed to",f.name )
-
-
-
-def start_log_writer():
- thread_log = threading.Thread(target = log_writer , args = () )
- thread_log.daemon = True
- thread_log.start()
-
-
-
-
-
-def send_data_in_fragment(data , sock):
- L_data = len(data)
- indices = random.sample(range(1,L_data-1), num_fragment-1)
- indices.sort()
- # print('indices=',indices)
-
- i_pre=0
- for i in indices:
- fragment_data = data[i_pre:i]
- i_pre=i
- # print('send ',len(fragment_data),' bytes')
-
- # sock.send(fragment_data)
- sock.sendall(fragment_data)
-
- time.sleep(fragment_sleep)
-
- fragment_data = data[i_pre:L_data]
- sock.sendall(fragment_data)
- # print('----------finish------------')
-
-
-
-
-if (__name__ == "__main__"):
- print('Logging disabled in Android version')
- # start_log_writer()
- print ("Now listening at: 127.0.0.1:"+str(listen_PORT))
- ThreadedServer('',listen_PORT).listen()
-
-
-
-
diff --git a/gfw/Android/v2rayN_http_config.json b/gfw/Android/v2rayN_http_config.json
deleted file mode 100644
index c1f512a..0000000
--- a/gfw/Android/v2rayN_http_config.json
+++ /dev/null
@@ -1,86 +0,0 @@
-{
- "log": {
- "loglevel": "warning"
- },
-
- "inbounds": [
- {
- "listen": "127.0.0.1",
- "port": 10808,
- "protocol": "socks",
- "settings": {
- "auth": "noauth",
- "udp": true,
- "userLevel": 8
- },
- "sniffing": {
- "destOverride": [
- "http",
- "tls"
- ],
- "enabled": true
- },
- "tag": "socks"
- },
- {
- "listen": "127.0.0.1",
- "port": 10809,
- "protocol": "http",
- "settings": {
- "userLevel": 8
- },
- "tag": "http"
- }
- ],
-
-
- "outbounds": [
-
- {
- "tag": "pyprox",
- "protocol": "http",
- "settings": {
- "servers": [
- {
- "address": "127.0.0.1",
- "port": 4500
- }
- ]
- }
- },
-
-
- {
- "protocol": "freedom",
- "settings": {},
- "tag": "direct"
- },
- {
- "protocol": "blackhole",
- "settings": {
- "response": {
- "type": "http"
- }
- },
- "tag": "block"
- }
- ],
-
-
-
-
- "routing": {
- "domainMatcher": "mph",
- "domainStrategy": "IPIfNonMatch",
- "rules": [
- {
- "type": "field",
- "port": "0-65535",
- "outboundTag": "pyprox",
- "enabled": true
- }
- ]
- }
-
-
-}
diff --git a/gfw/Direct_DoH/How_Make_Our_DoH/DoH_json_format_test.py b/gfw/Direct_DoH/How_Make_Our_DoH/DoH_json_format_test.py
deleted file mode 100644
index be18780..0000000
--- a/gfw/Direct_DoH/How_Make_Our_DoH/DoH_json_format_test.py
+++ /dev/null
@@ -1,68 +0,0 @@
-#!/usr/bin/env python3
-
-import requests # --> pip install requests
-import json
-
-
-
-# DNS_url = 'https://your.site:8443/mygoogle/resolve?name='
-# DNS_url = 'https://your.site:8443/mycloudflare/dns-query?name='
-
-DNS_url = 'https://8.8.8.8/resolve?name='
-# DNS_url = 'https://8.8.4.4/resolve?name='
-# DNS_url = 'https://1.1.1.1/dns-query?name='
-
-query = 'youtube.com'
-
-
-allow_insecure = True # set true to allow certificate domain mismatch
-
-
-class DNS_over_Fragment:
- def __init__(self):
- self.url = DNS_url
- self.req = requests.session()
-
-
- def query(self,server_name):
-
- quary_params = {
- 'name': server_name,
- 'type': 'A',
- 'ct': 'application/dns-json',
- }
-
-
- print(f'online DNS Query',server_name)
- try:
-
- query_url = self.url + server_name
- ans = self.req.get( query_url , params=quary_params , headers={'accept': 'application/dns-json'} , verify=(not allow_insecure) )
-
- # Parse the response as a DNS packet
- if (ans.status_code == 200):
- answer_msg = json.loads(ans.content)
-
- # resolved_ip = answer_msg['Answer'][0]['data']
- resolved_ip = None
-
- for x in answer_msg['Answer']:
- if (x['type'] == 1):
- resolved_ip = x['data'] # pick first ip in DNS answer
- break
-
- print(f'online DNS --> Resolved {server_name} to {resolved_ip}')
- return resolved_ip
- else:
- print(f'Error: {ans.status_code} {ans.reason}')
- except Exception as e:
- print(repr(e))
-
-
-
-
-if (__name__ == "__main__"):
- DoH = DNS_over_Fragment()
- DoH.query(query)
-
-
diff --git a/gfw/Direct_DoH/How_Make_Our_DoH/DoH_wire_format_test.py b/gfw/Direct_DoH/How_Make_Our_DoH/DoH_wire_format_test.py
deleted file mode 100644
index 01f4afa..0000000
--- a/gfw/Direct_DoH/How_Make_Our_DoH/DoH_wire_format_test.py
+++ /dev/null
@@ -1,73 +0,0 @@
-#!/usr/bin/env python3
-
-import dns.message # --> pip install dnspython
-import dns.rdatatype
-import requests # --> pip install requests
-import base64
-
-
-# DNS_url = 'https://your.site:8443/mygoogle/dns-query?dns='
-# DNS_url = 'https://your.site:8443/mycloudflare/dns-query?dns='
-
-# DNS_url = 'https://8.8.8.8/dns-query?dns='
-# DNS_url = 'https://8.8.4.4/dns-query?dns='
-DNS_url = 'https://1.1.1.1/dns-query?dns='
-# DNS_url = 'https://dns.electrotm.org/dns-query?dns='
-
-query = 'youtube.com'
-
-allow_insecure = True # set true to allow certificate domain mismatch
-
-
-class DNS_over_Fragment:
- def __init__(self):
- self.url = DNS_url
- self.req = requests.session()
-
-
- def query(self,server_name):
-
- quary_params = {
- # 'name': server_name, # no need for this when using dns wire-format , cause 400 err on some server
- 'type': 'A',
- 'ct': 'application/dns-message',
- }
-
-
- print(f'online DNS Query',server_name)
- try:
- query_message = dns.message.make_query(server_name,'A')
- query_wire = query_message.to_wire()
- query_base64 = base64.urlsafe_b64encode(query_wire).decode('utf-8')
- query_base64 = query_base64.replace('=','') # remove base64 padding to append in url
-
- query_url = self.url + query_base64
- ans = self.req.get( query_url , params=quary_params , headers={'accept': 'application/dns-message'} , verify=(not allow_insecure) )
-
- # Parse the response as a DNS packet
- if ans.status_code == 200 and ans.headers.get('content-type') == 'application/dns-message':
- answer_msg = dns.message.from_wire(ans.content)
-
- resolved_ip = None
- for x in answer_msg.answer:
- if (x.rdtype == dns.rdatatype.A):
- resolved_ip = x[0].address # pick first ip in DNS answer
- break
-
- print(f'online DNS --> Resolved {server_name} to {resolved_ip}')
- return resolved_ip
- else:
- print(f'Error: {ans.status_code} {ans.reason}')
- except Exception as e:
- print(repr(e))
-
-
-
-
-if (__name__ == "__main__"):
- DoH = DNS_over_Fragment()
- DoH.query(query)
-
-
-
-
diff --git a/gfw/Direct_DoH/How_Make_Our_DoH/README.md b/gfw/Direct_DoH/How_Make_Our_DoH/README.md
deleted file mode 100644
index ab695d9..0000000
--- a/gfw/Direct_DoH/How_Make_Our_DoH/README.md
+++ /dev/null
@@ -1,48 +0,0 @@
-# how to make your DoH server
-1. install nginx
-apt install nginx-light
-2. add these line in file
- /etc/nginx/sites-available/default
-
-# cloudflare HTTPS port [ 443 , 2053 , 2083 , 2087 , 2096 , 8443 ]
-server {
- listen 8443 ssl default_server;
- ssl_certificate /root/my_cert/your_cert.pem;
- ssl_certificate_key /root/my_cert/your_cert.key;
- location /mycloudflare/ {
- proxy_pass https://cloudflare-dns.com:443/;
- }
- location /mygoogle/ {
- proxy_pass https://dns.google:443/;
- }
-}
-
-
-3. reload nginx
-systemctl daemon-reload
-systemctl restart nginx
-
-4. use your DoH
-Json Format:
-DNS_url = 'https://your.site:8443/mygoogle/resolve?name='
-DNS_url = 'https://your.site:8443/mycloudflare/dns-query?name='
-Wire Format:
-DNS_url = 'https://your.site:8443/mygoogle/dns-query?dns='
-DNS_url = 'https://your.site:8443/mycloudflare/dns-query?dns='
-
-5. you can put your.site behind cloudflare but ensure that your.domain is resolved to clean ip
-
-# Additional Tutorial:
-1. we have two DNS query standard (some server only support WIRE format)
-JSON format:
-https://dns.google/resolve?name=yahoo.com
-https://cloudflare-dns.com/dns-query?name=yahoo.com
-WIRE format:
-https://dns.google/dns-query?dns=B64encode
-https://cloudflare-dns.com/dns-query?dns=B64encode
-2. test your server with curl
-curl -H "accept: application/dns-json" https://your.site:8443/mygoogle/resolve?name=yahoo.com
- curl -H "accept: application/dns-json" https://your.site:8443/mycloudflare/dns-query?name=yahoo.com
-
-
-
diff --git a/gfw/Direct_DoH/README.md b/gfw/Direct_DoH/README.md
deleted file mode 100644
index 8b5f4f5..0000000
--- a/gfw/Direct_DoH/README.md
+++ /dev/null
@@ -1,8 +0,0 @@
-# Direct DNS-Over-Https (DoH)
-
-# چیه این ؟
-- مستقیم تمام ip ها را از DNS over HTTPS (DoH) میگیرد بدون دخل و تصرف
-- مقدار DNS_url را باید گزینه ای بگذارید که ایپی اش مسدود نباشد. مثلا سرور گوگل 8.8.8.8 روی یک نت مسدود و روی نت دیگر باز است
-- اگر ip هایی که DoH برمیگرداند روی نت شما فیلتر نباشد ، سایت بالا خواهد آمد و محدودیت های comment و live و ... برطرف میشود
-- تعداد فرگمنت را بین 10 تا 100 امتحان کنید و زمان فرگمنت بین 0.001 تا 0.01
-- کافیست اسکریپت Direct_DoH.py را اجرا کنید مشابه توضیحات صفحه اول
diff --git a/gfw/Direct_DoH/pyprox_HTTPS_v2.0_DirectDoH.py b/gfw/Direct_DoH/pyprox_HTTPS_v2.0_DirectDoH.py
deleted file mode 100644
index 745946f..0000000
--- a/gfw/Direct_DoH/pyprox_HTTPS_v2.0_DirectDoH.py
+++ /dev/null
@@ -1,411 +0,0 @@
-#!/usr/bin/env python3
-
-import dns.message # --> pip install dnspython
-import dns.rdatatype
-import requests # --> pip install requests
-from pathlib import Path
-import os
-import base64
-import socket
-import threading
-import time
-import random
-
-
-listen_PORT = 4500 # pyprox listening to 127.0.0.1:listen_PORT
-
-num_fragment = 87 # total number of chunks that ClientHello devided into (chunks with random size)
-fragment_sleep = 0.001 # sleep between each fragment to make GFW-cache full so it forget previous chunks. LOL.
-
-log_every_N_sec = 30 # every 30 second , update log file with latest DNS-cache statistics
-
-allow_insecure = True # set true to allow certificate domain mismatch in DoH
-
-
-
-# DNS_url = 'https://8.8.4.4/dns-query?dns=' # blocked?
-# DNS_url = 'https://8.8.8.8/dns-query?dns=' # blocked?
-# DNS_url = 'https://1.1.1.1/dns-query?dns=' # blocked?
-# DNS_url = 'https://cloudflare-dns.com/dns-query?dns=' # blocked?
-# DNS_url = 'https://dns.google/dns-query?dns=' # blocked?
-# DNS_url = 'https://doh.opendns.com/dns-query?dns=' # blocked?
-# DNS_url = 'https://secure.avastdns.com/dns-query?dns=' # blocked?
-# DNS_url = 'https://doh.libredns.gr/dns-query?dns=' # blocked?
-# DNS_url = 'https://dns.electrotm.org/dns-query?dns='
-# DNS_url = 'https://dns.bitdefender.net/dns-query?dns='
-DNS_url = 'https://cluster-1.gac.edu/dns-query?dns='
-
-
-
-
-offline_DNS = {
-
-################## DNS over HTTPS IP Address (leave it intact , it must Exist) ######################
-'cloudflare-dns.com':'1.1.1.1',
-'dns.google':'8.8.8.8',
-'doh.opendns.com':'208.67.222.222',
-'secure.avastdns.com':'185.185.133.66',
-'doh.libredns.gr':'116.202.176.26',
-'dns.electrotm.org':'78.157.42.100',
-'dns.bitdefender.net':'34.84.232.67',
-'cluster-1.gac.edu':'138.236.128.101',
-##########################################################################
-
-}
-
-
-
-
-
-# ignore description below , its for old code , just leave it intact.
-my_socket_timeout = 21 # default for google is ~21 sec , recommend 60 sec unless you have low ram and need close soon
-first_time_sleep = 0.1 # speed control , avoid server crash if huge number of users flooding
-accept_time_sleep = 0.01 # avoid server crash on flooding request -> max 100 sockets per second
-
-
-DNS_cache = {} # resolved domains
-IP_DL_traffic = {} # download usage for each ip
-IP_UL_traffic = {} # upload usage for each ip
-
-
-class DNS_over_Fragment:
- def __init__(self):
- self.url = DNS_url
- self.req = requests.session()
- self.fragment_proxy = {
- 'https': 'http://127.0.0.1:'+str(listen_PORT)
- }
-
-
-
- def query(self,server_name):
-
- offline_ip = offline_DNS.get(server_name,None)
- if(offline_ip!=None):
- print('offline DNS -->',server_name,offline_ip)
- return offline_ip
-
- cache_ip = DNS_cache.get(server_name,None)
- if(cache_ip!=None):
- print('cached DNS -->',server_name,cache_ip)
- return cache_ip
-
- quary_params = {
- # 'name': server_name, # no need for this when using dns wire-format , cause 400 err on some server
- 'type': 'A',
- 'ct': 'application/dns-message',
- }
-
-
- print(f'online DNS Query',server_name)
- try:
- query_message = dns.message.make_query(server_name,'A')
- query_wire = query_message.to_wire()
- query_base64 = base64.urlsafe_b64encode(query_wire).decode('utf-8')
- query_base64 = query_base64.replace('=','') # remove base64 padding to append in url
-
- query_url = self.url + query_base64
- ans = self.req.get( query_url , params=quary_params , headers={'accept': 'application/dns-message'} , proxies=self.fragment_proxy , verify=(not allow_insecure))
-
- # Parse the response as a DNS packet
- if ans.status_code == 200 and ans.headers.get('content-type') == 'application/dns-message':
- answer_msg = dns.message.from_wire(ans.content)
-
- resolved_ip = None
- for x in answer_msg.answer:
- if (x.rdtype == dns.rdatatype.A):
- resolved_ip = x[0].address # pick first ip in DNS answer
- DNS_cache[server_name] = resolved_ip
- print("################# DNS Cache is : ####################")
- print(DNS_cache) # print DNS cache , it usefull to track all resolved IPs , to be used later.
- print("#####################################################")
- break
-
- print(f'online DNS --> Resolved {server_name} to {resolved_ip}')
- return resolved_ip
- else:
- print(f'Error: {ans.status_code} {ans.reason}')
- except Exception as e:
- print(repr(e))
-
-
-
-
-
-
-
-
-
-class ThreadedServer(object):
- def __init__(self, host, port):
- self.DoH = DNS_over_Fragment()
- self.host = host
- self.port = port
- self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
- self.sock.bind((self.host, self.port))
-
- def listen(self):
- self.sock.listen(128) # up to 128 concurrent unaccepted socket queued , the more is refused untill accepting those.
-
- while True:
- client_sock , client_addr = self.sock.accept()
- client_sock.settimeout(my_socket_timeout)
-
- time.sleep(accept_time_sleep) # avoid server crash on flooding request
- thread_up = threading.Thread(target = self.my_upstream , args =(client_sock,) )
- thread_up.daemon = True #avoid memory leak by telling os its belong to main program , its not a separate program , so gc collect it when thread finish
- thread_up.start()
-
-
-
- def handle_client_request(self,client_socket):
- # Receive the CONNECT request from the client
- data = client_socket.recv(16384)
-
-
- if(data[:7]==b'CONNECT'):
- server_name , server_port = self.extract_servername_and_port(data)
- elif( (data[:3]==b'GET')
- or (data[:4]==b'POST')
- or (data[:4]==b'HEAD')
- or (data[:7]==b'OPTIONS')
- or (data[:3]==b'PUT')
- or (data[:6]==b'DELETE')
- or (data[:5]==b'PATCH')
- or (data[:5]==b'TRACE') ):
-
- q_line = str(data).split('\r\n')
- q_req = q_line[0].split()
- q_method = q_req[0]
- q_url = q_req[1]
- q_url = q_url.replace('http://','https://')
- print('************************@@@@@@@@@@@@***************************')
- print('redirect',q_method,'http to HTTPS',q_url)
- response_data = 'HTTP/1.1 302 Found\r\nLocation: '+q_url+'\r\nProxy-agent: MyProxy/1.0\r\n\r\n'
- client_socket.sendall(response_data.encode())
- client_socket.close()
- return None
- else:
- print('Unknown Method',str(data[:10]))
- response_data = b'HTTP/1.1 400 Bad Request\r\nProxy-agent: MyProxy/1.0\r\n\r\n'
- client_socket.sendall(response_data)
- client_socket.close()
- return None
-
-
- print(server_name,'-->',server_port)
-
- try:
- server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- server_socket.settimeout(my_socket_timeout)
- server_socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) #force localhost kernel to send TCP packet immediately (idea: @free_the_internet)
-
- try:
- socket.inet_aton(server_name)
- # print('legal IP')
- server_IP = server_name
- except socket.error:
- # print('Not IP , its domain , try to resolve it')
- server_IP = self.DoH.query(server_name)
-
- server_socket.connect((server_IP, server_port))
- # Send HTTP 200 OK
- response_data = b'HTTP/1.1 200 Connection established\r\nProxy-agent: MyProxy/1.0\r\n\r\n'
- client_socket.sendall(response_data)
- return server_socket
- except Exception as e:
- print(repr(e))
- # Send HTTP ERR 502
- response_data = b'HTTP/1.1 502 Bad Gateway (is IP filtered?)\r\nProxy-agent: MyProxy/1.0\r\n\r\n'
- client_socket.sendall(response_data)
- client_socket.close()
- server_socket.close()
- return None
-
-
-
-
-
-
-
- def my_upstream(self, client_sock):
- first_flag = True
- backend_sock = self.handle_client_request(client_sock)
-
- if(backend_sock==None):
- client_sock.close()
- return False
-
- this_ip = backend_sock.getpeername()[0]
- if(this_ip not in IP_UL_traffic):
- IP_UL_traffic[this_ip] = 0
-
-
- while True:
- try:
- if( first_flag == True ):
- first_flag = False
-
- time.sleep(first_time_sleep) # speed control + waiting for packet to fully recieve
- data = client_sock.recv(16384)
- #print('len data -> ',str(len(data)))
- #print('user talk :')
-
- if data:
- thread_down = threading.Thread(target = self.my_downstream , args = (backend_sock , client_sock) )
- thread_down.daemon = True
- thread_down.start()
- # backend_sock.sendall(data)
- send_data_in_fragment(data,backend_sock)
- IP_UL_traffic[this_ip] = IP_UL_traffic[this_ip] + len(data)
-
- else:
- raise Exception('cli syn close')
-
- else:
- data = client_sock.recv(16384)
- if data:
- backend_sock.sendall(data)
- IP_UL_traffic[this_ip] = IP_UL_traffic[this_ip] + len(data)
- else:
- raise Exception('cli pipe close')
-
- except Exception as e:
- #print('upstream : '+ repr(e) )
- time.sleep(2) # wait two second for another thread to flush
- client_sock.close()
- backend_sock.close()
- return False
-
-
-
-
- def my_downstream(self, backend_sock , client_sock):
- this_ip = backend_sock.getpeername()[0]
- if(this_ip not in IP_DL_traffic):
- IP_DL_traffic[this_ip] = 0
-
-
- first_flag = True
- while True:
- try:
- if( first_flag == True ):
- first_flag = False
- data = backend_sock.recv(16384)
- if data:
- client_sock.sendall(data)
- IP_DL_traffic[this_ip] = IP_DL_traffic[this_ip] + len(data)
- else:
- raise Exception('backend pipe close at first')
-
- else:
- data = backend_sock.recv(16384)
- if data:
- client_sock.sendall(data)
- IP_DL_traffic[this_ip] = IP_DL_traffic[this_ip] + len(data)
- else:
- raise Exception('backend pipe close')
-
- except Exception as e:
- #print('downstream '+backend_name +' : '+ repr(e))
- time.sleep(2) # wait two second for another thread to flush
- backend_sock.close()
- client_sock.close()
- return False
-
-
-
- def extract_servername_and_port(self,data):
- host_and_port = str(data).split()[1]
- host,port = host_and_port.split(':')
- return (host,int(port))
-
-
-
-def merge_all_dicts():
- full_DNS = {**DNS_cache, **offline_DNS} # merge two dict , need python 3.5 or up
- inv_DNS = { v:k for k, v in full_DNS.items()} # inverse mapping to look for domain given ip
- stats = {}
- for ip in IP_DL_traffic:
- up = round(IP_UL_traffic[ip]/(1024.0),3)
- down = round(IP_DL_traffic[ip]/(1024.0),3)
- host = inv_DNS.get(ip,'?')
- if((up>down) and (down<1.0)): # download below 1KB
- maybe_filter = 'maybe'
- else:
- maybe_filter = '-------'
-
- su = f'UL={up} KB:'
- sd = f'DL={down} KB:'
- sf = f'filtered={maybe_filter}:'
- sh = f'Host={host}:'
- stats[ip] = ':'+su+sd+sf+sh
- return stats
-
-
-
-# only run in separate thread
-def log_writer():
- file_name = 'DNS_IP_traffic_info.txt'
- BASE_DIR = Path(__file__).resolve().parent
- log_file_path = os.path.join(BASE_DIR,file_name)
-
- with open(log_file_path, "w") as f:
- while True:
- time.sleep(log_every_N_sec)
- all_stats_info = merge_all_dicts()
- f.seek(0)
- f.write('\n########### new DNS resolved : ##############\n')
- f.write(str(DNS_cache).replace(',',',\n'))
- f.write('\n#############################################\n')
- f.write('\n########### ALL INFO : ######################\n')
- f.write(str(all_stats_info).replace('\'','').replace(',','\n').replace(':','\t'))
- f.write('\n#############################################\n')
- f.flush()
- f.truncate()
- print("info file writed to",f.name )
-
-
-
-def start_log_writer():
- thread_log = threading.Thread(target = log_writer , args = () )
- thread_log.daemon = True
- thread_log.start()
-
-
-
-
-
-def send_data_in_fragment(data , sock):
- L_data = len(data)
- indices = random.sample(range(1,L_data-1), num_fragment-1)
- indices.sort()
- # print('indices=',indices)
-
- i_pre=0
- for i in indices:
- fragment_data = data[i_pre:i]
- i_pre=i
- # print('send ',len(fragment_data),' bytes')
-
- # sock.send(fragment_data)
- sock.sendall(fragment_data)
-
- time.sleep(fragment_sleep)
-
- fragment_data = data[i_pre:L_data]
- sock.sendall(fragment_data)
- print('----------finish------------')
-
-
-
-
-if (__name__ == "__main__"):
- start_log_writer()
- print ("Now listening at: 127.0.0.1:"+str(listen_PORT))
- ThreadedServer('',listen_PORT).listen()
-
-
-
-
diff --git a/gfw/Irancell/README.md b/gfw/Irancell/README.md
deleted file mode 100644
index e3eaa2b..0000000
--- a/gfw/Irancell/README.md
+++ /dev/null
@@ -1,3 +0,0 @@
-# بهینه شده برای ایرانسل
-- یوتیوب و توییتر
-- اگر کار نکرد تعداد فرگمنت را از 14 به 87 افزایش و زمان فرگمنت را از 0.01 به 0.001 کاهش دهید
diff --git a/gfw/Irancell/pyprox_HTTPS_v1.0_irancell.py b/gfw/Irancell/pyprox_HTTPS_v1.0_irancell.py
deleted file mode 100644
index 26d2e8e..0000000
--- a/gfw/Irancell/pyprox_HTTPS_v1.0_irancell.py
+++ /dev/null
@@ -1,490 +0,0 @@
-#!/usr/bin/env python3
-
-import dns.message # --> pip install dnspython
-import dns.rdatatype
-import requests # --> pip install requests
-from pathlib import Path
-import os
-import base64
-import socket
-import threading
-import time
-import random
-
-
-listen_PORT = 4500 # pyprox listening to 127.0.0.1:listen_PORT
-
-num_fragment = 14 # total number of chunks that ClientHello devided into (chunks with random size)
-fragment_sleep = 0.01 # sleep between each fragment to make GFW-cache full so it forget previous chunks. LOL.
-
-log_every_N_sec = 10 # every 30 second , update log file with latest DNS-cache statistics
-
-# DNS_url = 'https://cloudflare-dns.com/dns-query?dns=' # not working in iran , ip blocked
-# DNS_url = 'https://dns.google/dns-query?dns=' # not working in iran , ip blocked
-# DNS_url = 'https://doh.opendns.com/dns-query?dns=' # not working in iran , ip blocked
-# DNS_url = 'https://secure.avastdns.com/dns-query?dns=' # not working in iran , ip blocked
-# DNS_url = 'https://doh.libredns.gr/dns-query?dns=' # not working in iran , ip blocked
-DNS_url = 'https://dns.electrotm.org/dns-query?dns='
-# DNS_url = 'https://dns.bitdefender.net/dns-query?dns='
-# DNS_url = 'https://cluster-1.gac.edu/dns-query?dns='
-
-
-
-
-offline_DNS = {
-
-
-
-# ################# twitter working pack ###################
-'ocsp.digicert.com': '192.229.211.108',
-
-'api.twitter.com': '104.244.42.66',
-'twitter.com': '104.244.42.1',
-'pbs.twimg.com': '93.184.220.70',
-'abs-0.twimg.com': '104.244.43.131',
-'abs.twimg.com': '152.199.24.185',
-'video.twimg.com': '192.229.220.133',
-'t.co': '104.244.42.69',
-'ton.local.twitter.com':'104.244.42.1',
-# ##########################################################
-
-
-
-##################### Google working pack ###################
-'ocsp.pki.goog': '172.217.16.195',
-'googleads.g.doubleclick.net': '45.157.177.108',
-'fonts.gstatic.com': '142.250.185.227',
-'rr2---sn-vh5ouxa-hju6.googlevideo.com': '213.202.6.141',
-'jnn-pa.googleapis.com': '45.157.177.108',
-'static.doubleclick.net': '202.61.195.218',
-'rr4---sn-hju7en7k.googlevideo.com': '74.125.167.74',
-'rr1---sn-hju7en7r.googlevideo.com': '74.125.167.87',
-'play.google.com': '142.250.184.238',
-'rr3---sn-vh5ouxa-hjuz.googlevideo.com': '134.0.218.206',
-'rr3---sn-hju7enel.googlevideo.com': '74.125.98.40',
-'download.visualstudio.microsoft.com': '68.232.34.200',
-'ocsp.pki.goog': '172.217.16.195',
-'i.ytimg.com': '142.250.186.150',
-'rr2---sn-hju7enel.googlevideo.com': '74.125.98.39',
-'rr2---sn-hju7en7k.googlevideo.com': '74.125.167.72',
-'googleads.g.doubleclick.net': '45.157.177.108',
-'rr3---sn-4g5lznl6.googlevideo.com': '74.125.173.40',
-'jnn-pa.googleapis.com': '89.58.57.45',
-'rr3---sn-hju7en7k.googlevideo.com': '74.125.167.73',
-'rr1---sn-hju7enll.googlevideo.com': '74.125.98.6',
-'rr6---sn-hju7en7r.googlevideo.com': '74.125.167.92',
-'play.google.com': '216.58.212.174',
-'www.gstatic.com': '142.250.185.99',
-'apis.google.com': '172.217.23.110',
-'adservice.google.com': '202.61.195.218',
-'mail.google.com': '142.250.186.37',
-'accounts.google.com': '172.217.16.205',
-
-# 'lh3.googleusercontent.com': '193.26.157.66', # filtered
-'lh3.googleusercontent.com':'142.251.167.132',
-
-'accounts.youtube.com': '172.217.16.206',
-'ssl.gstatic.com': '142.250.184.195',
-'fonts.gstatic.com': '172.217.23.99',
-'rr4---sn-hju7enll.googlevideo.com': '74.125.98.9', # good
-'rr2---sn-hju7enll.googlevideo.com': '74.125.98.7',
-'rr1---sn-hju7enel.googlevideo.com': '74.125.98.38',
-'rr5---sn-vh5ouxa-hjuz.googlevideo.com': '134.0.218.208',
-'i1.ytimg.com': '172.217.18.14',
-'plos.org': '162.159.135.42',
-'fonts.googleapis.com': '89.58.57.45',
-'genweb.plos.org': '104.26.1.141',
-'static.ads-twitter.com': '146.75.120.157',
-'www.google-analytics.com': '142.250.185.174',
-'rr1---sn-vh5ouxa-hju6.googlevideo.com': '213.202.6.140',
-'rr5---sn-vh5ouxa-hju6.googlevideo.com': '213.202.6.144',
-'rr3---sn-hju7enel.googlevideo.com': '74.125.98.40',
-'rr5---sn-nv47zn7y.googlevideo.com': '173.194.15.74',
-'safebrowsing.googleapis.com': '202.61.195.218',
-'static.doubleclick.net': '193.26.157.66',
-'rr5---sn-vh5ouxa-hju6.googlevideo.com': '213.202.6.144',
-'rr1---sn-hju7en7r.googlevideo.com': '74.125.167.87',
-'rr4---sn-vh5ouxa-hju6.googlevideo.com': '213.202.6.143',
-'rr4---sn-hju7en7r.googlevideo.com': '74.125.167.90',
-'r1---sn-hju7enel.googlevideo.com': '74.125.98.38',
-'rr1---sn-nv47zn7r.googlevideo.com': '173.194.15.38',
-'rr2---sn-vh5ouxa-hjuz.googlevideo.com': '134.0.218.205',
-'rr4---sn-nv47zn7r.googlevideo.com': '173.194.15.41',
-'rr4---sn-hju7en7r.googlevideo.com': '74.125.167.90',
-
-
-'rr4---sn-nv47znel.googlevideo.com': '74.125.98.7', # good
-'rr4---sn-nv47lnl7.googlevideo.com':'74.125.98.7',
-'rr4---sn-hju7enll.googlevideo.com':'74.125.98.7',
-'rr1---sn-vh5ouxa-hju6.googlevideo.com':'74.125.98.7',
-'rr3---sn-hju7enel.googlevideo.com':'74.125.98.7',
-'rr5---sn-hju7enll.googlevideo.com':'74.125.98.7',
-'rr5---sn-vh5ouxa-hjuz.googlevideo.com':'74.125.98.7',
-'rr1---sn-nv47ln7z.googlevideo.com':'74.125.98.7',
-'rr3---sn-vh5ouxa-hju6.googlevideo.com': '74.125.98.7',
-
-
-'www.google.com': '142.250.186.36',
-# 'www.google.com': '216.239.38.120',
-'youtube.com':'216.239.38.120',
-'www.youtube.com':'216.239.38.120',
-'i.ytimg.com':'216.239.38.120',
-
-# 'yt3.ggpht.com': '64.233.165.198', # filtered
-# 'yt3.ggpht.com': '142.250.179.161', # filtered
-# 'yt3.ggpht.com': '142.250.186.65', # sometimes work
-'yt3.ggpht.com': '142.250.186.36', # most of times work
-#######################################################
-
-
-################## DNS over HTTPS IP Address (leave it intact , it must Exist) ######################
-'cloudflare-dns.com':'1.1.1.1', # not working in iran , ip blocked
-'dns.google':'8.8.8.8', # not working in iran , ip blocked
-'doh.opendns.com':'208.67.222.222', # not working in iran , ip blocked
-'secure.avastdns.com':'185.185.133.66', # not working in iran , ip blocked
-'doh.libredns.gr':'116.202.176.26', # not working in iran , ip blocked
-'dns.electrotm.org':'78.157.42.100',
-'dns.bitdefender.net':'34.84.232.67',
-'cluster-1.gac.edu':'138.236.128.101',
-##########################################################################
-
-}
-
-
-
-
-
-# ignore description below , its for old code , just leave it intact.
-my_socket_timeout = 21 # default for google is ~21 sec , recommend 60 sec unless you have low ram and need close soon
-first_time_sleep = 0.1 # speed control , avoid server crash if huge number of users flooding
-accept_time_sleep = 0.01 # avoid server crash on flooding request -> max 100 sockets per second
-
-
-DNS_cache = {} # resolved domains
-IP_DL_traffic = {} # download usage for each ip
-IP_UL_traffic = {} # upload usage for each ip
-
-
-class DNS_over_Fragment:
- def __init__(self):
- self.url = DNS_url
- self.req = requests.session()
- self.fragment_proxy = {
- 'https': 'http://127.0.0.1:'+str(listen_PORT)
- }
-
-
-
- def query(self,server_name):
-
- offline_ip = offline_DNS.get(server_name,None)
- if(offline_ip!=None):
- print('offline DNS -->',server_name,offline_ip)
- return offline_ip
-
- cache_ip = DNS_cache.get(server_name,None)
- if(cache_ip!=None):
- print('cached DNS -->',server_name,cache_ip)
- return cache_ip
-
- quary_params = {
- # 'name': server_name, # no need for this when using dns wire-format , cause 400 err on some server
- 'type': 'A',
- 'ct': 'application/dns-message',
- }
-
-
- print(f'online DNS Query',server_name)
- try:
- query_message = dns.message.make_query(server_name,'A')
- query_wire = query_message.to_wire()
- query_base64 = base64.urlsafe_b64encode(query_wire).decode('utf-8')
- query_base64 = query_base64.replace('=','') # remove base64 padding to append in url
-
- query_url = self.url + query_base64
- ans = self.req.get( query_url , params=quary_params , headers={'accept': 'application/dns-message'} , proxies=self.fragment_proxy)
-
- # Parse the response as a DNS packet
- if ans.status_code == 200 and ans.headers.get('content-type') == 'application/dns-message':
- answer_msg = dns.message.from_wire(ans.content)
-
- resolved_ip = None
- for x in answer_msg.answer:
- if (x.rdtype == dns.rdatatype.A):
- resolved_ip = x[0].address # pick first ip in DNS answer
- DNS_cache[server_name] = resolved_ip
- print("################# DNS Cache is : ####################")
- print(DNS_cache) # print DNS cache , it usefull to track all resolved IPs , to be used later.
- print("#####################################################")
- break
-
- print(f'online DNS --> Resolved {server_name} to {resolved_ip}')
- return resolved_ip
- else:
- print(f'Error: {ans.status_code} {ans.reason}')
- except Exception as e:
- print(repr(e))
-
-
-
-
-
-
-
-
-
-class ThreadedServer(object):
- def __init__(self, host, port):
- self.DoH = DNS_over_Fragment()
- self.host = host
- self.port = port
- self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
- self.sock.bind((self.host, self.port))
-
- def listen(self):
- self.sock.listen(128) # up to 128 concurrent unaccepted socket queued , the more is refused untill accepting those.
-
- while True:
- client_sock , client_addr = self.sock.accept()
- client_sock.settimeout(my_socket_timeout)
-
- time.sleep(accept_time_sleep) # avoid server crash on flooding request
- thread_up = threading.Thread(target = self.my_upstream , args =(client_sock,) )
- thread_up.daemon = True #avoid memory leak by telling os its belong to main program , its not a separate program , so gc collect it when thread finish
- thread_up.start()
-
-
-
- def handle_client_request(self,client_socket):
- # Receive the CONNECT request from the client
- data = client_socket.recv(16384)
-
-
- if(data[:7]==b'CONNECT'):
- server_name , server_port = self.extract_servername_and_port(data)
- elif( (data[:3]==b'GET') or (data[:4]==b'POST')):
- q_line = str(data).split('\r\n')
- q_url = q_line[0].split()[1]
- q_url = q_url.replace('http://','https://')
- print('redirect http to HTTPS',q_url)
- response_data = 'HTTP/1.1 302 Found\r\nLocation: '+q_url+'\r\nProxy-agent: MyProxy/1.0\r\n\r\n'
- client_socket.sendall(response_data.encode())
- client_socket.close()
- return None
- else:
- print('Unknown Method',str(data[:10]))
- response_data = b'HTTP/1.1 400 Bad Request\r\nProxy-agent: MyProxy/1.0\r\n\r\n'
- client_socket.sendall(response_data)
- client_socket.close()
- return None
-
-
- print(server_name,'-->',server_port)
-
- try:
- server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- server_socket.settimeout(my_socket_timeout)
- server_socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) #force localhost kernel to send TCP packet immediately (idea: @free_the_internet)
-
- server_IP = self.DoH.query(server_name)
- server_socket.connect((server_IP, server_port))
- # Send HTTP 200 OK
- response_data = b'HTTP/1.1 200 Connection established\r\nProxy-agent: MyProxy/1.0\r\n\r\n'
- client_socket.sendall(response_data)
- return server_socket
- except Exception as e:
- print(repr(e))
- # Send HTTP ERR 502
- response_data = b'HTTP/1.1 502 Bad Gateway\r\nProxy-agent: MyProxy/1.0\r\n\r\n'
- client_socket.sendall(response_data)
- client_socket.close()
- server_socket.close()
- return None
-
-
-
-
-
-
-
- def my_upstream(self, client_sock):
- first_flag = True
- backend_sock = self.handle_client_request(client_sock)
-
- if(backend_sock==None):
- client_sock.close()
- return False
-
- this_ip = backend_sock.getpeername()[0]
- if(this_ip not in IP_UL_traffic):
- IP_UL_traffic[this_ip] = 0
-
-
- while True:
- try:
- if( first_flag == True ):
- first_flag = False
-
- time.sleep(first_time_sleep) # speed control + waiting for packet to fully recieve
- data = client_sock.recv(16384)
- #print('len data -> ',str(len(data)))
- #print('user talk :')
-
- if data:
- thread_down = threading.Thread(target = self.my_downstream , args = (backend_sock , client_sock) )
- thread_down.daemon = True
- thread_down.start()
- # backend_sock.sendall(data)
- send_data_in_fragment(data,backend_sock)
- IP_UL_traffic[this_ip] = IP_UL_traffic[this_ip] + len(data)
-
- else:
- raise Exception('cli syn close')
-
- else:
- data = client_sock.recv(16384)
- if data:
- backend_sock.sendall(data)
- IP_UL_traffic[this_ip] = IP_UL_traffic[this_ip] + len(data)
- else:
- raise Exception('cli pipe close')
-
- except Exception as e:
- #print('upstream : '+ repr(e) )
- time.sleep(2) # wait two second for another thread to flush
- client_sock.close()
- backend_sock.close()
- return False
-
-
-
-
- def my_downstream(self, backend_sock , client_sock):
- this_ip = backend_sock.getpeername()[0]
- if(this_ip not in IP_DL_traffic):
- IP_DL_traffic[this_ip] = 0
-
-
- first_flag = True
- while True:
- try:
- if( first_flag == True ):
- first_flag = False
- data = backend_sock.recv(16384)
- if data:
- client_sock.sendall(data)
- IP_DL_traffic[this_ip] = IP_DL_traffic[this_ip] + len(data)
- else:
- raise Exception('backend pipe close at first')
-
- else:
- data = backend_sock.recv(16384)
- if data:
- client_sock.sendall(data)
- IP_DL_traffic[this_ip] = IP_DL_traffic[this_ip] + len(data)
- else:
- raise Exception('backend pipe close')
-
- except Exception as e:
- #print('downstream '+backend_name +' : '+ repr(e))
- time.sleep(2) # wait two second for another thread to flush
- backend_sock.close()
- client_sock.close()
- return False
-
-
-
- def extract_servername_and_port(self,data):
- host_and_port = str(data).split()[1]
- host,port = host_and_port.split(':')
- return (host,int(port))
-
-
-
-def merge_all_dicts():
- full_DNS = {**DNS_cache, **offline_DNS} # merge two dict , need python 3.5 or up
- inv_DNS = { v:k for k, v in full_DNS.items()} # inverse mapping to look for domain given ip
- stats = {}
- for ip in IP_DL_traffic:
- up = round(IP_UL_traffic[ip]/(1024.0),3)
- down = round(IP_DL_traffic[ip]/(1024.0),3)
- host = inv_DNS.get(ip,'?')
- if((up>down) and (down<1.0)): # download below 1KB
- maybe_filter = 'maybe'
- else:
- maybe_filter = '-------'
-
- su = f'UL={up} KB:'
- sd = f'DL={down} KB:'
- sf = f'filtered={maybe_filter}:'
- sh = f'Host={host}:'
- stats[ip] = ':'+su+sd+sf+sh
- return stats
-
-
-
-# only run in separate thread
-def log_writer():
- file_name = 'DNS_IP_traffic_info.txt'
- BASE_DIR = Path(__file__).resolve().parent
- log_file_path = os.path.join(BASE_DIR,file_name)
-
- with open(log_file_path, "w") as f:
- while True:
- time.sleep(log_every_N_sec)
- all_stats_info = merge_all_dicts()
- f.seek(0)
- f.write('\n########### new DNS resolved : ##############\n')
- f.write(str(DNS_cache).replace(',',',\n'))
- f.write('\n#############################################\n')
- f.write('\n########### ALL INFO : ######################\n')
- f.write(str(all_stats_info).replace('\'','').replace(',','\n').replace(':','\t'))
- f.write('\n#############################################\n')
- f.flush()
- f.truncate()
- print("info file writed to",f.name )
-
-
-
-def start_log_writer():
- thread_log = threading.Thread(target = log_writer , args = () )
- thread_log.daemon = True
- thread_log.start()
-
-
-
-
-
-def send_data_in_fragment(data , sock):
- L_data = len(data)
- indices = random.sample(range(1,L_data-1), num_fragment-1)
- indices.sort()
- # print('indices=',indices)
-
- i_pre=0
- for i in indices:
- fragment_data = data[i_pre:i]
- i_pre=i
- # print('send ',len(fragment_data),' bytes')
-
- # sock.send(fragment_data)
- sock.sendall(fragment_data)
-
- time.sleep(fragment_sleep)
-
- fragment_data = data[i_pre:L_data]
- sock.sendall(fragment_data)
- print('----------finish------------')
-
-
-
-
-if (__name__ == "__main__"):
- # start_log_writer()
- print ("Now listening at: 127.0.0.1:"+str(listen_PORT))
- ThreadedServer('',listen_PORT).listen()
-
-
-
-
diff --git a/gfw/Irancell/v2rayN_HTTPS_config.json b/gfw/Irancell/v2rayN_HTTPS_config.json
deleted file mode 100644
index c1f512a..0000000
--- a/gfw/Irancell/v2rayN_HTTPS_config.json
+++ /dev/null
@@ -1,86 +0,0 @@
-{
- "log": {
- "loglevel": "warning"
- },
-
- "inbounds": [
- {
- "listen": "127.0.0.1",
- "port": 10808,
- "protocol": "socks",
- "settings": {
- "auth": "noauth",
- "udp": true,
- "userLevel": 8
- },
- "sniffing": {
- "destOverride": [
- "http",
- "tls"
- ],
- "enabled": true
- },
- "tag": "socks"
- },
- {
- "listen": "127.0.0.1",
- "port": 10809,
- "protocol": "http",
- "settings": {
- "userLevel": 8
- },
- "tag": "http"
- }
- ],
-
-
- "outbounds": [
-
- {
- "tag": "pyprox",
- "protocol": "http",
- "settings": {
- "servers": [
- {
- "address": "127.0.0.1",
- "port": 4500
- }
- ]
- }
- },
-
-
- {
- "protocol": "freedom",
- "settings": {},
- "tag": "direct"
- },
- {
- "protocol": "blackhole",
- "settings": {
- "response": {
- "type": "http"
- }
- },
- "tag": "block"
- }
- ],
-
-
-
-
- "routing": {
- "domainMatcher": "mph",
- "domainStrategy": "IPIfNonMatch",
- "rules": [
- {
- "type": "field",
- "port": "0-65535",
- "outboundTag": "pyprox",
- "enabled": true
- }
- ]
- }
-
-
-}
diff --git a/gfw/asset/IP_Log.png b/gfw/asset/IP_Log.png
deleted file mode 100644
index 7da923c..0000000
Binary files a/gfw/asset/IP_Log.png and /dev/null differ
diff --git a/gfw/asset/customize_params.png b/gfw/asset/customize_params.png
deleted file mode 100644
index 4972372..0000000
Binary files a/gfw/asset/customize_params.png and /dev/null differ
diff --git a/gfw/asset/firefox_proxy.png b/gfw/asset/firefox_proxy.png
deleted file mode 100644
index 5d8473b..0000000
Binary files a/gfw/asset/firefox_proxy.png and /dev/null differ
diff --git a/gfw/asset/install_packages.png b/gfw/asset/install_packages.png
deleted file mode 100644
index 4c38411..0000000
Binary files a/gfw/asset/install_packages.png and /dev/null differ
diff --git a/gfw/asset/neko_bypass_app.jpg b/gfw/asset/neko_bypass_app.jpg
deleted file mode 100644
index bcf4f43..0000000
Binary files a/gfw/asset/neko_bypass_app.jpg and /dev/null differ
diff --git a/gfw/asset/neko_http_config.jpg b/gfw/asset/neko_http_config.jpg
deleted file mode 100644
index 590df7b..0000000
Binary files a/gfw/asset/neko_http_config.jpg and /dev/null differ
diff --git a/gfw/asset/neko_http_menu.jpg b/gfw/asset/neko_http_menu.jpg
deleted file mode 100644
index 893539a..0000000
Binary files a/gfw/asset/neko_http_menu.jpg and /dev/null differ
diff --git a/gfw/asset/offline_DNS.png b/gfw/asset/offline_DNS.png
deleted file mode 100644
index 8ab37cc..0000000
Binary files a/gfw/asset/offline_DNS.png and /dev/null differ
diff --git a/gfw/asset/slide2.png b/gfw/asset/slide2.png
deleted file mode 100644
index 82a3762..0000000
Binary files a/gfw/asset/slide2.png and /dev/null differ
diff --git a/gfw/asset/swiss_army.png b/gfw/asset/swiss_army.png
deleted file mode 100644
index 522686c..0000000
Binary files a/gfw/asset/swiss_army.png and /dev/null differ
diff --git a/gfw/asset/temp.txt b/gfw/asset/temp.txt
deleted file mode 100644
index a9a5aec..0000000
--- a/gfw/asset/temp.txt
+++ /dev/null
@@ -1 +0,0 @@
-tmp
diff --git a/gfw/asset/v2ray_custom.png b/gfw/asset/v2ray_custom.png
deleted file mode 100644
index e723dfd..0000000
Binary files a/gfw/asset/v2ray_custom.png and /dev/null differ