Git initial commit
This commit is contained in:
commit
16260400ca
6
led_blink.py
Executable file
6
led_blink.py
Executable file
@ -0,0 +1,6 @@
|
||||
from machine import Pin
|
||||
import time
|
||||
led = machine.Pin("LED", machine.Pin.OUT)
|
||||
while True:
|
||||
led.toggle()
|
||||
time.sleep(1)
|
320
pico_proxy.py
Executable file
320
pico_proxy.py
Executable file
@ -0,0 +1,320 @@
|
||||
import network
|
||||
import socket
|
||||
import _thread
|
||||
from time import sleep
|
||||
from collections import deque
|
||||
from uasyncio import Event
|
||||
import re
|
||||
|
||||
|
||||
class MicroProxy:
|
||||
wait_symbols = {
|
||||
0: "-",
|
||||
1: "\\",
|
||||
2: "|",
|
||||
3: "/"
|
||||
}
|
||||
def __init__(
|
||||
self, n_threads_max = 2, buf_byte_size=1024, client_timeout=60):
|
||||
self._n_threads = 0
|
||||
self._n_threads_max = n_threads_max
|
||||
self._buf_byte_size = buf_byte_size
|
||||
self._client_timeout = client_timeout
|
||||
|
||||
self._thread_events = []
|
||||
self._job_queue = deque((), 1024)
|
||||
self._threads_lock = _thread.allocate_lock()
|
||||
self._max_lock = _thread.allocate_lock()
|
||||
self._listener_event = Event()
|
||||
self._is_listening = False
|
||||
|
||||
def set_max_thread_count(self, n_threads_max):
|
||||
self._max_lock.acquire()
|
||||
self._n_threads_max = n_threads_max
|
||||
if self._n_threads > self._n_threads_max:
|
||||
self.rescale(self._n_threads_max)
|
||||
self._max_lock.release()
|
||||
|
||||
def max_thread_count(self):
|
||||
return self._n_threads_max
|
||||
|
||||
def thread_count(self):
|
||||
return self._n_threads
|
||||
|
||||
|
||||
def _set_listener(self):
|
||||
# Check what kind of socket is needed to
|
||||
# bind onto.
|
||||
# Take the first possible socket and the
|
||||
# required IP info for binding.
|
||||
self._addr_listen = socket.getaddrinfo(
|
||||
self._addr, self._port
|
||||
)[0][-1]
|
||||
|
||||
if hasattr(self, '_socket_listen') and self._socket_listen is not None:
|
||||
self.stop()
|
||||
self._socket_listen = socket.socket(
|
||||
socket.AF_INET,
|
||||
(
|
||||
socket.SOCK_STREAM
|
||||
if self._proxy_type == "TCP"
|
||||
else
|
||||
socket.SOCK_DGRAM
|
||||
)
|
||||
)
|
||||
self._socket_listen.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||
|
||||
def listen(self, addr, port, proxy_type="TCP", backlog=0):
|
||||
if not self._is_listening:
|
||||
self._addr = addr
|
||||
self._port = port
|
||||
self._proxy_type = "UDP" if not proxy_type == "TCP" else proxy_type
|
||||
|
||||
self._set_listener()
|
||||
|
||||
self._socket_listen.bind(self._addr_listen)
|
||||
self._socket_listen.listen(backlog)
|
||||
|
||||
self.rescale(self._n_threads_max)
|
||||
#_thread.start_new_thread(
|
||||
# self._listener_thread,(self._listener_event,)
|
||||
#)
|
||||
print(f"init done for serving on {self._addr_listen}")
|
||||
self._is_listening = True
|
||||
return self._listener_event
|
||||
|
||||
def stop(self):
|
||||
if self._is_listening:
|
||||
self._listener_event.set()
|
||||
ctr = 0
|
||||
while self._listener_event.is_set():
|
||||
print(
|
||||
(
|
||||
"Waiting for listener thread to finish... "
|
||||
f"{MicroProxy.wait_symbols[ctr%4]}\r"
|
||||
),
|
||||
end=""
|
||||
)
|
||||
ctr += 1
|
||||
sleep(0.5)
|
||||
else:
|
||||
print("Listener thread finished closing safely.")
|
||||
self.rescale(0)
|
||||
self._socket_listen.close()
|
||||
del self._socket_listen
|
||||
self._is_listening = False
|
||||
|
||||
def rescale(self, n_threads):
|
||||
new_n_threads = min(
|
||||
(
|
||||
n_threads
|
||||
if isinstance(n_threads, int) and max(-1,n_threads) >= 0
|
||||
else
|
||||
self._n_threads
|
||||
), self._n_threads_max
|
||||
)
|
||||
old_n_threads = self._n_threads
|
||||
if self._n_threads < new_n_threads:
|
||||
self._spin_up(new_n_threads - self._n_threads)
|
||||
elif self._n_threads > new_n_threads:
|
||||
self._spin_down(self._n_threads - new_n_threads)
|
||||
if new_n_threads != old_n_threads:
|
||||
print(
|
||||
"Changed worker thread size "
|
||||
f"from {old_n_threads} to {new_n_threads}."
|
||||
)
|
||||
|
||||
def _spin_up(self, thread_cnt_new):
|
||||
self._threads_lock.acquire()
|
||||
|
||||
new_thread_events = [
|
||||
Event()
|
||||
for _ in range(thread_cnt_new)
|
||||
]
|
||||
self._thread_events.extend(new_thread_events)
|
||||
|
||||
for idx, event in enumerate(new_thread_events):
|
||||
_thread.start_new_thread(
|
||||
self._worker_thread, (
|
||||
#thread_idx is 1 based; 0 is master.
|
||||
event, self._n_threads+idx+1
|
||||
)
|
||||
)
|
||||
self._n_threads = len(self._thread_events)
|
||||
|
||||
self._threads_lock.release()
|
||||
|
||||
def _spin_down(self, thread_cnt_del):
|
||||
self._threads_lock.acquire()
|
||||
remaining = self._n_threads - thread_cnt_del
|
||||
|
||||
thread_events_stop = self._thread_events[remaining:]
|
||||
self._thread_events = self._thread_events[:remaining]
|
||||
for event in thread_events_stop:
|
||||
event.set()
|
||||
|
||||
ctr = 0
|
||||
while any(
|
||||
event.is_set()
|
||||
for event in thread_events_stop
|
||||
):
|
||||
print(
|
||||
(
|
||||
"Wait for worker threads to finish... "
|
||||
f"{MicroProxy.wait_symbols[ctr%4]}\r"
|
||||
),
|
||||
end=""
|
||||
)
|
||||
ctr += 1
|
||||
sleep(0.5)
|
||||
else:
|
||||
print("Worker threads finished spinning down safely.")
|
||||
for idx in range(len(thread_events_stop)-1, -1, -1):
|
||||
del thread_events_stop[idx]
|
||||
del thread_events_stop
|
||||
|
||||
self._threads_lock.release()
|
||||
|
||||
|
||||
def _listener_thread(self, event):
|
||||
print("listening started")
|
||||
while not event.is_set():
|
||||
print("stuff todo?")
|
||||
conn, addr = self._socket_listen.accept()
|
||||
print(f"incoming connection from {addr}")
|
||||
self._job_queue.append((addr, conn))
|
||||
# clear event to indicate it stopped at spindown task
|
||||
event.clear()
|
||||
|
||||
def _worker_thread(self, event, thread_id):
|
||||
print(f"Worker thread {thread_id}: starting.")
|
||||
socket_client_thread = socket.socket(
|
||||
socket.AF_INET,
|
||||
(
|
||||
socket.SOCK_STREAM
|
||||
if self._proxy_type == "TCP"
|
||||
else
|
||||
socket.SOCK_DGRAM
|
||||
)
|
||||
)
|
||||
socket_client_thread.settimeout(self._client_timeout)
|
||||
while not event.is_set():
|
||||
if len(self._job_queue) > 0:
|
||||
try:
|
||||
addr, conn = self._job_queue.popleft()
|
||||
except:
|
||||
# Maybe another thread was faster inbetween.
|
||||
# If so, simply continue
|
||||
continue
|
||||
print(
|
||||
f"Worker thread {thread_id}:",
|
||||
f"handling connection of '{addr}'"
|
||||
)
|
||||
request = conn.recv(self._buf_byte_size)
|
||||
protocol, host_domain, port = MicroProxy.proxy_forward_filter(
|
||||
request.decode()
|
||||
)
|
||||
print(
|
||||
f"Worker thread {thread_id}: ",
|
||||
f"{protocol}://{host_domain}:{port}"
|
||||
)
|
||||
try:
|
||||
client_addr = socket.getaddrinfo(host_domain, port)[0][-1]
|
||||
socket_client_thread.connect(client_addr)
|
||||
socket_client_thread.sendall(request)
|
||||
has_response = False
|
||||
while not has_response:
|
||||
response = socket_client_thread.recv(self._buf_byte_size)
|
||||
if len(response) > 0:
|
||||
has_response = True
|
||||
print("send response")
|
||||
conn.send(response)
|
||||
print("Done sending response")
|
||||
except OSError as exc:
|
||||
if exc.errno != 115:
|
||||
print("OOOPS?!?!?!", exc)
|
||||
else:
|
||||
print(
|
||||
f"Timeout ... increase by 2: {self._client_timeout}",
|
||||
f"-> {self._client_timeout*2}"
|
||||
)
|
||||
self._client_timeout = self._client_timeout * 2
|
||||
socket_client_thread.close()
|
||||
conn.close()
|
||||
print("finished closing")
|
||||
else:
|
||||
sleep(0.1)
|
||||
print(f"Worker thread {thread_id}: finished safely and shutting down.")
|
||||
# clear event to indicate it stopped at spindown task
|
||||
event.clear()
|
||||
|
||||
def proxy_forward_filter(request):
|
||||
header = request.split('\n')[0]
|
||||
url = header.split()[1]
|
||||
port = 80
|
||||
protocol = None
|
||||
has_port = False
|
||||
has_protocol = False
|
||||
|
||||
if url.startswith("http"):
|
||||
protocol, host_part = url.split('://')
|
||||
has_protocol = True
|
||||
else:
|
||||
host_part = url
|
||||
|
||||
if ":" in host_part:
|
||||
splitter = host_part.split(':')
|
||||
host_domain = splitter[0]
|
||||
port = int(splitter[1])
|
||||
has_port = True
|
||||
elif "/" in host_part:
|
||||
host_domain = host_part.split('/')[0]
|
||||
|
||||
if not has_protocol and has_port:
|
||||
if port == 443:
|
||||
protocol = "https"
|
||||
else:
|
||||
protocol = "http"
|
||||
if not has_port:
|
||||
if protocol == "https":
|
||||
port = 443
|
||||
else:
|
||||
port = 80
|
||||
return (protocol, host_domain, port)
|
||||
|
||||
|
||||
def connect_wlan(ssid, password):
|
||||
wlan = network.WLAN(network.STA_IF)
|
||||
wlan.active(True)
|
||||
wlan.connect(ssid, password)
|
||||
|
||||
max_wait = 10
|
||||
while max_wait > 0:
|
||||
if wlan.status() < 0 or wlan.status() >= 3:
|
||||
break
|
||||
max_wait -= 1
|
||||
print(
|
||||
"waiting for connection...",
|
||||
f"{MicroProxy.wait_symbols[max_wait%4]}\r",
|
||||
end=""
|
||||
)
|
||||
sleep(1)
|
||||
if wlan.status() != 3:
|
||||
raise RuntimeError('network connection failed')
|
||||
else:
|
||||
status = wlan.ifconfig()
|
||||
print(f'conntected, ip = {status[0]}')
|
||||
return wlan
|
||||
|
||||
def main():
|
||||
ssid = 'Lars-WLAN'
|
||||
password = '0243LHBS18021909'
|
||||
wlan = connect_wlan(ssid, password)
|
||||
|
||||
mitm = MicroProxy(n_threads_max=1)
|
||||
event = mitm.listen(addr='0.0.0.0', port=8080)
|
||||
mitm._listener_thread(event)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
265
picoproxy.py
Executable file
265
picoproxy.py
Executable file
@ -0,0 +1,265 @@
|
||||
import _thread
|
||||
import socket
|
||||
import network
|
||||
from select import select
|
||||
from uasyncio import Event
|
||||
from time import sleep
|
||||
#from threading import Thread, Event
|
||||
|
||||
|
||||
class PicoProxy:
|
||||
### CLS FUNCTIONS #############################################################
|
||||
wait_symbols = "-\|/"
|
||||
|
||||
def _get_socket(proxy_type="TCP"):
|
||||
return socket.socket(
|
||||
socket.AF_INET,
|
||||
(
|
||||
socket.SOCK_STREAM
|
||||
if proxy_type == "TCP"
|
||||
else
|
||||
socket.SOCK_DGRAM
|
||||
)
|
||||
)
|
||||
def init_tunnle(request, sock_in, sock_out, host, port):
|
||||
if request.startswith(b"CONNECT"):
|
||||
try:
|
||||
addr_info = socket.getaddrinfo(host,port)[0][-1]
|
||||
sock_out.connect(addr_info)
|
||||
sock_in.sendall(b"HTTP/1.1 200 established\r\n\r\n")
|
||||
except Exception as e:
|
||||
print("Cannot initiate proxy tunnel:", e)
|
||||
|
||||
|
||||
def proxy_forward_filter(request):
|
||||
#looks ugly, yes; but is able to run on Pico W micro-controller :D
|
||||
header = request.split('\n')[0]
|
||||
url = header.split()[1]
|
||||
port = 80
|
||||
protocol = None
|
||||
has_port = False
|
||||
has_protocol = False
|
||||
|
||||
if url.startswith("http"):
|
||||
protocol, host_part = url.split('://')
|
||||
has_protocol = True
|
||||
else:
|
||||
host_part = url
|
||||
|
||||
if ":" in host_part:
|
||||
splitter = host_part.split(':')
|
||||
host_domain = splitter[0]
|
||||
port = int(splitter[1])
|
||||
has_port = True
|
||||
elif "/" in host_part:
|
||||
host_domain = host_part.split('/')[0]
|
||||
|
||||
if not has_protocol and has_port:
|
||||
if port == 443:
|
||||
protocol = "https"
|
||||
else:
|
||||
protocol = "http"
|
||||
if not has_port:
|
||||
if protocol == "https":
|
||||
port = 443
|
||||
else:
|
||||
port = 80
|
||||
return (protocol, host_domain, port)
|
||||
|
||||
|
||||
|
||||
### OBJ FUNCTIONS #############################################################
|
||||
def __init__(self, buf_byte_size=4096, client_timeout=60):
|
||||
self._buf_byte_size = buf_byte_size
|
||||
self._client_timeout = client_timeout
|
||||
|
||||
self._listener_event = Event()
|
||||
|
||||
self._is_listening = False
|
||||
self._incoming = []
|
||||
self._outgoing = []
|
||||
self._channel_map = {}
|
||||
self._channel_init = {}
|
||||
self._channel_from_client = []
|
||||
|
||||
|
||||
|
||||
def _set_listener(self):
|
||||
# Check what kind of socket is needed to
|
||||
# bind onto.
|
||||
# Take the first possible socket and the
|
||||
# required IP info for binding.
|
||||
self._addr_listen = socket.getaddrinfo(
|
||||
self._addr, self._port
|
||||
)[0][-1]
|
||||
|
||||
if hasattr(self, '_socket_listen') and self._socket_listen is not None:
|
||||
self.stop()
|
||||
self._socket_listen = PicoProxy._get_socket()
|
||||
self._socket_listen.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||
|
||||
def listen(self, addr, port, proxy_type="TCP", backlog=0):
|
||||
if not self._is_listening:
|
||||
self._addr = addr
|
||||
self._port = port
|
||||
self._proxy_type = "UDP" if not proxy_type == "TCP" else proxy_type
|
||||
|
||||
self._set_listener()
|
||||
|
||||
self._socket_listen.bind(self._addr_listen)
|
||||
self._socket_listen.listen(backlog)
|
||||
|
||||
self._incoming.append(self._socket_listen)
|
||||
|
||||
#self._listen_thread = Thread(
|
||||
# target=self._listener_thread, args=(self._listener_event,)
|
||||
#)
|
||||
#self._listen_thread.start()
|
||||
#_thread.start_new_thread(
|
||||
# self._listener_thread, (self._listener_event,)
|
||||
#)
|
||||
print(f"init done for serving on {self._addr_listen}")
|
||||
self._is_listening = True
|
||||
self._listener_thread(self._listener_event)
|
||||
|
||||
def stop(self):
|
||||
if self._is_listening:
|
||||
self._listener_event.set()
|
||||
ctr = 0
|
||||
while not self._listener_event.is_set():
|
||||
print(
|
||||
(
|
||||
"Waiting for listener thread to finish... "
|
||||
f"{PicoProxy.wait_symbols[ctr%len(PicoProxy.wait_symbols)]}\r"
|
||||
),
|
||||
end=""
|
||||
)
|
||||
ctr += 1
|
||||
sleep(0.5)
|
||||
else:
|
||||
print("Listener thread finished closing safely.")
|
||||
self._socket_listen.close()
|
||||
self._is_listening = False
|
||||
self._incoming.clear()
|
||||
self._outgoing.clear()
|
||||
self._channel_map.clear()
|
||||
self._channel_init.clear()
|
||||
self._channel_from_client.clear()
|
||||
|
||||
def is_active(self):
|
||||
return not self._listener_event.is_set()
|
||||
|
||||
|
||||
def _listener_thread(self, event):
|
||||
while self._incoming and not event.is_set():
|
||||
inrecv, outsend, excpt = select(
|
||||
self._incoming, self._outgoing, self._incoming
|
||||
)
|
||||
for sock in inrecv:
|
||||
if sock is self._socket_listen:
|
||||
self._handle_connection_incoming()
|
||||
elif (
|
||||
id(sock) in self._channel_init and not self._channel_init[id(sock)] and
|
||||
sock not in self._channel_from_client
|
||||
):
|
||||
continue
|
||||
else:
|
||||
data = sock.recv(self._buf_byte_size)
|
||||
if data:
|
||||
self._handle_connection_receive(sock, data)
|
||||
else:
|
||||
self._handle_connection_close(sock)
|
||||
event.clear()
|
||||
|
||||
def _handle_connection_incoming(self):
|
||||
conn, addr = self._socket_listen.accept()
|
||||
conn.settimeout(self._client_timeout)
|
||||
reverse_conn = PicoProxy._get_socket(self._proxy_type)
|
||||
reverse_conn.settimeout(self._client_timeout)
|
||||
|
||||
self._channel_from_client.append(conn)
|
||||
|
||||
self._incoming.append(conn)
|
||||
|
||||
self._channel_map[id(conn)] = reverse_conn
|
||||
self._channel_map[id(reverse_conn)] = conn
|
||||
|
||||
self._channel_init[id(conn)] = False
|
||||
self._channel_init[id(reverse_conn)] = False
|
||||
|
||||
def _handle_connection_receive(self, sock, data):
|
||||
reverse_sock = self._channel_map[id(sock)]
|
||||
if not self._channel_init[id(sock)] and not self._channel_init[id(reverse_sock)]:
|
||||
protocol, host_domain, port = PicoProxy.proxy_forward_filter(data.decode())
|
||||
if protocol == "https" or port == 443:
|
||||
PicoProxy.init_tunnle(
|
||||
data, sock, reverse_sock, host_domain, port
|
||||
)
|
||||
else:
|
||||
addr_info = socket.getaddrinfo(host_domain,port)[0][-1]
|
||||
reverse_sock.connect(addr_info)
|
||||
#not a tunnel request, directly forward
|
||||
reverse_sock.sendall(data)
|
||||
self._incoming.append(reverse_sock)
|
||||
self._channel_init[id(sock)] = True
|
||||
self._channel_init[id(reverse_sock)] = True
|
||||
else:
|
||||
reverse_sock.sendall(data)
|
||||
|
||||
def _handle_connection_close(self, sock):
|
||||
reverse_sock = self._channel_map[id(sock)]
|
||||
for s in (sock, reverse_sock):
|
||||
if s in self._outgoing:
|
||||
self._outgoing.remove(s)
|
||||
if s in self._incoming:
|
||||
self._incoming.remove(s)
|
||||
if s in self._channel_from_client:
|
||||
self._channel_from_client.remove(s)
|
||||
s.close()
|
||||
del self._channel_init[id(s)]
|
||||
del self._channel_map[id(s)]
|
||||
|
||||
def connect_wlan(ssid, password):
|
||||
wlan = network.WLAN(network.STA_IF)
|
||||
wlan.active(True)
|
||||
wlan.connect(ssid, password)
|
||||
|
||||
max_wait = 10
|
||||
while max_wait > 0:
|
||||
if wlan.status() < 0 or wlan.status() >= 3:
|
||||
break
|
||||
max_wait -= 1
|
||||
print(
|
||||
"waiting for connection...",
|
||||
f"{PicoProxy.wait_symbols[max_wait%4]}\r",
|
||||
end=""
|
||||
)
|
||||
sleep(0.5)
|
||||
if wlan.status() != 3:
|
||||
raise RuntimeError('network connection failed')
|
||||
else:
|
||||
status = wlan.ifconfig()
|
||||
print(f'conntected, ip = {status[0]}')
|
||||
return wlan
|
||||
|
||||
def main():
|
||||
ssid = 'WLAN-NAME'
|
||||
password = 'WLAN-PASSWORD'
|
||||
wlan = connect_wlan(ssid, password)
|
||||
proxy = PicoProxy()
|
||||
proxy.listen(addr='0.0.0.0', port=8080)
|
||||
# ctr = 0
|
||||
# cnt = len(PicoProxy.wait_symbols)
|
||||
# while proxy.is_active():
|
||||
# ctr = (ctr + 1)%cnt
|
||||
# print(
|
||||
# "Currently doing proxy stuff...",
|
||||
# f"{PicoProxy.wait_symbols[ctr]}\r",
|
||||
# end=""
|
||||
# )
|
||||
# sleep(0.5)
|
||||
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
242
picoproxy_not_functional_recheck.py
Executable file
242
picoproxy_not_functional_recheck.py
Executable file
@ -0,0 +1,242 @@
|
||||
import socket
|
||||
from time import sleep
|
||||
from queue import Queue
|
||||
from threading import Thread, Event
|
||||
from select import select
|
||||
|
||||
|
||||
class PicoProxy:
|
||||
### CLS FUNCTIONS #############################################################
|
||||
wait_symbols = "-\|/"
|
||||
|
||||
def _get_socket(proxy_type="TCP"):
|
||||
return socket.socket(
|
||||
socket.AF_INET,
|
||||
(
|
||||
socket.SOCK_STREAM
|
||||
if proxy_type == "TCP"
|
||||
else
|
||||
socket.SOCK_DGRAM
|
||||
)
|
||||
)
|
||||
def init_tunnle(request, sock_in, sock_out, host, port):
|
||||
if request.startswith(b"CONNECT"):
|
||||
try:
|
||||
sock_out.connect((host,port))
|
||||
sock_in.sendall(b"HTTP/1.1 200 established\r\n\r\n")
|
||||
except Exception as e:
|
||||
print("Cannot initiate HTTPS connection:", e)
|
||||
|
||||
|
||||
def proxy_forward_filter(request):
|
||||
#looks ugly, yes; but is able to run on Pico W micro-controller :D
|
||||
header = request.split('\n')[0]
|
||||
url = header.split()[1]
|
||||
port = 80
|
||||
protocol = None
|
||||
has_port = False
|
||||
has_protocol = False
|
||||
|
||||
if url.startswith("http"):
|
||||
protocol, host_part = url.split('://')
|
||||
has_protocol = True
|
||||
else:
|
||||
host_part = url
|
||||
|
||||
if ":" in host_part:
|
||||
splitter = host_part.split(':')
|
||||
host_domain = splitter[0]
|
||||
port = int(splitter[1])
|
||||
has_port = True
|
||||
elif "/" in host_part:
|
||||
host_domain = host_part.split('/')[0]
|
||||
|
||||
if not has_protocol and has_port:
|
||||
if port == 443:
|
||||
protocol = "https"
|
||||
else:
|
||||
protocol = "http"
|
||||
if not has_port:
|
||||
if protocol == "https":
|
||||
port = 443
|
||||
else:
|
||||
port = 80
|
||||
return (protocol, host_domain, port)
|
||||
|
||||
|
||||
|
||||
### OBJ FUNCTIONS #############################################################
|
||||
def __init__(self, buf_byte_size=4096, client_timeout=0.5):
|
||||
self._buf_byte_size = buf_byte_size
|
||||
self._client_timeout = client_timeout
|
||||
|
||||
self._listener_event = Event()
|
||||
|
||||
self._is_listening = False
|
||||
self._incoming = []
|
||||
self._outgoing = []
|
||||
self._channel_msg_map = {}
|
||||
self._channel_map = {}
|
||||
self._channel_init = {}
|
||||
self._channel_from_client = []
|
||||
|
||||
|
||||
|
||||
def _set_listener(self):
|
||||
# Check what kind of socket is needed to
|
||||
# bind onto.
|
||||
# Take the first possible socket and the
|
||||
# required IP info for binding.
|
||||
self._addr_listen = socket.getaddrinfo(
|
||||
self._addr, self._port
|
||||
)[0][-1]
|
||||
|
||||
if hasattr(self, '_socket_listen') and self._socket_listen is not None:
|
||||
self.stop()
|
||||
self._socket_listen = PicoProxy._get_socket()
|
||||
self._socket_listen.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||
|
||||
def listen(self, addr, port, proxy_type="TCP", backlog=0):
|
||||
if not self._is_listening:
|
||||
self._addr = addr
|
||||
self._port = port
|
||||
self._proxy_type = "UDP" if not proxy_type == "TCP" else proxy_type
|
||||
|
||||
self._set_listener()
|
||||
|
||||
self._socket_listen.bind(self._addr_listen)
|
||||
self._socket_listen.listen(backlog)
|
||||
|
||||
self._incoming.append(self._socket_listen)
|
||||
|
||||
self._listen_thread = Thread(
|
||||
target=self._listener_thread, args=(self._listener_event,)
|
||||
)
|
||||
self._listen_thread.start()
|
||||
print(f"init done for serving on {self._addr_listen}")
|
||||
self._is_listening = True
|
||||
|
||||
def stop(self):
|
||||
if self._is_listening:
|
||||
self._listener_event.set()
|
||||
ctr = 0
|
||||
while self._listen_thread.is_alive():
|
||||
print(
|
||||
(
|
||||
"Waiting for listener thread to finish... "
|
||||
f"{PicoProxy.wait_symbols[ctr%len(PicoProxy.wait_symbols)]}\r"
|
||||
),
|
||||
end=""
|
||||
)
|
||||
ctr += 1
|
||||
sleep(0.5)
|
||||
else:
|
||||
print("Listener thread finished closing safely.")
|
||||
self._socket_listen.close()
|
||||
self._is_listening = False
|
||||
self._incoming.clear()
|
||||
self._outgoing.clear()
|
||||
self._channel_msg_map.clear()
|
||||
self._channel_map.clear()
|
||||
self._channel_init.clear()
|
||||
|
||||
def join(self):
|
||||
if self._is_listening:
|
||||
self._listen_thread.join()
|
||||
|
||||
|
||||
def _listener_thread(self, event):
|
||||
while self._incoming and not event.is_set():
|
||||
inrecv, outsend, excpt = select(
|
||||
self._incoming, self._outgoing, self._incoming
|
||||
)
|
||||
for sock in inrecv:
|
||||
if sock is self._socket_listen:
|
||||
self._handle_connection_incoming()
|
||||
elif (
|
||||
sock in self._channel_init and not self._channel_init[sock] and
|
||||
sock not in self._channel_from_client
|
||||
):
|
||||
continue
|
||||
else:
|
||||
data = sock.recv(self._buf_byte_size)
|
||||
if data:
|
||||
self._handle_connection_receive(sock, data)
|
||||
else:
|
||||
self._handle_connection_close(sock)
|
||||
# for sock in outsend:
|
||||
# self._handle_connection_send(sock)
|
||||
# for sock in excpt:
|
||||
# self._handle_connection_error(sock)
|
||||
event.clear()
|
||||
|
||||
def _handle_connection_incoming(self):
|
||||
conn, addr = self._socket_listen.accept()
|
||||
reverse_conn = PicoProxy._get_socket(self._proxy_type)
|
||||
|
||||
self._channel_from_client.append(conn)
|
||||
|
||||
self._incoming.append(conn)
|
||||
|
||||
self._channel_map[conn] = reverse_conn
|
||||
self._channel_map[reverse_conn] = conn
|
||||
|
||||
self._channel_msg_map[conn] = Queue()
|
||||
self._channel_msg_map[reverse_conn] = Queue()
|
||||
|
||||
self._channel_init[conn] = False
|
||||
self._channel_init[reverse_conn] = False
|
||||
|
||||
def _handle_connection_receive(self, sock, data):
|
||||
reverse_sock = self._channel_map[sock]
|
||||
if not self._channel_init[sock] and not self._channel_init[reverse_sock]:
|
||||
protocol, host_domain, port = PicoProxy.proxy_forward_filter(data.decode())
|
||||
if protocol == "https" or port == 443:
|
||||
PicoProxy.init_tunnle(
|
||||
data, sock, reverse_sock, host_domain, port
|
||||
)
|
||||
else:
|
||||
reverse_sock.connect((host_domain,port))
|
||||
#not a tunnel request, directly forward
|
||||
reverse_sock.sendall(data)
|
||||
self._incoming.append(reverse_sock)
|
||||
self._channel_init[sock] = True
|
||||
self._channel_init[reverse_sock] = True
|
||||
else:
|
||||
reverse_sock.sendall(data)
|
||||
# self._channel_msg_map[reverse_sock].put(data)
|
||||
# if reverse_sock not in self._outgoing:
|
||||
# self._outgoing.append(reverse_sock)
|
||||
|
||||
def _handle_connection_send(self, sock):
|
||||
try:
|
||||
msg = self._channel_msg_map[sock].get_nowait()
|
||||
except Queue.Empty:
|
||||
self._outgoing.remove(sock)
|
||||
else:
|
||||
sock.sendall(msg)
|
||||
|
||||
def _handle_connection_close(self, sock):
|
||||
reverse_sock = self._channel_map[sock]
|
||||
for s in (sock, reverse_sock):
|
||||
if s in self._outgoing:
|
||||
self._outgoing.remove(s)
|
||||
if s in self._incoming:
|
||||
self._incoming.remove(s)
|
||||
if s in self._channel_from_client:
|
||||
self._channel_from_client.remove(s)
|
||||
s.close()
|
||||
del self._channel_msg_map[s]
|
||||
del self._channel_init[s]
|
||||
del self._channel_map[s]
|
||||
|
||||
def _handle_connection_error(self, sock):
|
||||
self._handle_connection_close(sock)
|
||||
|
||||
def main():
|
||||
mitm = PicoProxy()
|
||||
mitm.listen(addr='0.0.0.0', port=8080)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
519
proxy.py
Executable file
519
proxy.py
Executable file
@ -0,0 +1,519 @@
|
||||
import socket
|
||||
import ssl
|
||||
from time import sleep
|
||||
from queue import Queue
|
||||
from threading import Thread, Event, Lock, get_native_id
|
||||
from select import select
|
||||
|
||||
|
||||
|
||||
class MicroProxy:
|
||||
### CLS FUNCTIONS #############################################################
|
||||
wait_symbols = "-\|/"
|
||||
|
||||
def _get_socket(proxy_type="TCP"):
|
||||
return socket.socket(
|
||||
socket.AF_INET,
|
||||
(
|
||||
socket.SOCK_STREAM
|
||||
if proxy_type == "TCP"
|
||||
else
|
||||
socket.SOCK_DGRAM
|
||||
)
|
||||
)
|
||||
def init_tunnle(request, sock_in, sock_out, host, port):
|
||||
if request.startswith(b"CONNECT"):
|
||||
try:
|
||||
sock_out.connect((host,port))
|
||||
sock_in.sendall(b"HTTP/1.1 200 established\r\n\r\n")
|
||||
except Exception as e:
|
||||
print("Cannot initiate proxy tunnel:", e)
|
||||
|
||||
|
||||
def proxy_forward_filter(request):
|
||||
#looks ugly, yes; but is able to run on Pico W micro-controller :D
|
||||
header = request.split('\n')[0]
|
||||
url = header.split()[1]
|
||||
port = 80
|
||||
protocol = None
|
||||
has_port = False
|
||||
has_protocol = False
|
||||
|
||||
if url.startswith("http"):
|
||||
protocol, host_part = url.split('://')
|
||||
has_protocol = True
|
||||
else:
|
||||
host_part = url
|
||||
|
||||
if ":" in host_part:
|
||||
splitter = host_part.split(':')
|
||||
host_domain = splitter[0]
|
||||
port = int(splitter[1])
|
||||
has_port = True
|
||||
elif "/" in host_part:
|
||||
host_domain = host_part.split('/')[0]
|
||||
|
||||
if not has_protocol and has_port:
|
||||
if port == 443:
|
||||
protocol = "https"
|
||||
else:
|
||||
protocol = "http"
|
||||
if not has_port:
|
||||
if protocol == "https":
|
||||
port = 443
|
||||
else:
|
||||
port = 80
|
||||
return (protocol, host_domain, port)
|
||||
|
||||
|
||||
|
||||
### OBJ FUNCTIONS #############################################################
|
||||
def __init__(self, buf_byte_size=4096, client_timeout=0.5):
|
||||
self._buf_byte_size = buf_byte_size
|
||||
self._client_timeout = client_timeout
|
||||
|
||||
self._listener_event = Event()
|
||||
|
||||
self._is_listening = False
|
||||
self._incoming = []
|
||||
self._outgoing = []
|
||||
self._channel_map = {}
|
||||
self._channel_init = {}
|
||||
self._channel_from_client = []
|
||||
|
||||
|
||||
|
||||
def _set_listener(self):
|
||||
# Check what kind of socket is needed to
|
||||
# bind onto.
|
||||
# Take the first possible socket and the
|
||||
# required IP info for binding.
|
||||
self._addr_listen = socket.getaddrinfo(
|
||||
self._addr, self._port
|
||||
)[0][-1]
|
||||
|
||||
if hasattr(self, '_socket_listen') and self._socket_listen is not None:
|
||||
self.stop()
|
||||
self._socket_listen = MicroProxy._get_socket()
|
||||
self._socket_listen.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||
|
||||
def listen(self, addr, port, proxy_type="TCP", backlog=0):
|
||||
if not self._is_listening:
|
||||
self._addr = addr
|
||||
self._port = port
|
||||
self._proxy_type = "UDP" if not proxy_type == "TCP" else proxy_type
|
||||
|
||||
self._set_listener()
|
||||
|
||||
self._socket_listen.bind(self._addr_listen)
|
||||
self._socket_listen.listen(backlog)
|
||||
|
||||
self._incoming.append(self._socket_listen)
|
||||
|
||||
self._listen_thread = Thread(
|
||||
target=self._listener_thread, args=(self._listener_event,)
|
||||
)
|
||||
self._listen_thread.start()
|
||||
print(f"init done for serving on {self._addr_listen}")
|
||||
self._is_listening = True
|
||||
|
||||
def stop(self):
|
||||
if self._is_listening:
|
||||
self._listener_event.set()
|
||||
ctr = 0
|
||||
while self._listen_thread.is_alive():
|
||||
print(
|
||||
(
|
||||
"Waiting for listener thread to finish... "
|
||||
f"{MicroProxy.wait_symbols[ctr%len(MicroProxy.wait_symbols)]}\r"
|
||||
),
|
||||
end=""
|
||||
)
|
||||
ctr += 1
|
||||
sleep(0.5)
|
||||
else:
|
||||
print("Listener thread finished closing safely.")
|
||||
self._socket_listen.close()
|
||||
self._is_listening = False
|
||||
self._incoming.clear()
|
||||
self._outgoing.clear()
|
||||
self._channel_map.clear()
|
||||
self._channel_init.clear()
|
||||
|
||||
def join(self):
|
||||
if self._is_listening:
|
||||
self._listen_thread.join()
|
||||
|
||||
|
||||
def _listener_thread(self, event):
|
||||
while self._incoming and not event.is_set():
|
||||
inrecv, outsend, excpt = select(
|
||||
self._incoming, self._outgoing, self._incoming
|
||||
)
|
||||
for sock in inrecv:
|
||||
if sock is self._socket_listen:
|
||||
self._handle_connection_incoming()
|
||||
elif (
|
||||
sock in self._channel_init and not self._channel_init[sock] and
|
||||
sock not in self._channel_from_client
|
||||
):
|
||||
continue
|
||||
else:
|
||||
data = sock.recv(self._buf_byte_size)
|
||||
if data:
|
||||
self._handle_connection_receive(sock, data)
|
||||
else:
|
||||
self._handle_connection_close(sock)
|
||||
event.clear()
|
||||
|
||||
def _handle_connection_incoming(self):
|
||||
conn, addr = self._socket_listen.accept()
|
||||
conn.settimeout(self._client_timeout)
|
||||
reverse_conn = MicroProxy._get_socket(self._proxy_type)
|
||||
reverse_conn.settimeout(self._client_timeout)
|
||||
|
||||
self._channel_from_client.append(conn)
|
||||
|
||||
self._incoming.append(conn)
|
||||
|
||||
self._channel_map[conn] = reverse_conn
|
||||
self._channel_map[reverse_conn] = conn
|
||||
|
||||
self._channel_init[conn] = False
|
||||
self._channel_init[reverse_conn] = False
|
||||
|
||||
def _handle_connection_receive(self, sock, data):
|
||||
reverse_sock = self._channel_map[sock]
|
||||
if not self._channel_init[sock] and not self._channel_init[reverse_sock]:
|
||||
protocol, host_domain, port = MicroProxy.proxy_forward_filter(data.decode())
|
||||
if protocol == "https" or port == 443:
|
||||
MicroProxy.init_tunnle(
|
||||
data, sock, reverse_sock, host_domain, port
|
||||
)
|
||||
else:
|
||||
reverse_sock.connect((host_domain,port))
|
||||
#not a tunnel request, directly forward
|
||||
reverse_sock.sendall(data)
|
||||
self._incoming.append(reverse_sock)
|
||||
self._channel_init[sock] = True
|
||||
self._channel_init[reverse_sock] = True
|
||||
else:
|
||||
reverse_sock.sendall(data)
|
||||
|
||||
def _handle_connection_close(self, sock):
|
||||
reverse_sock = self._channel_map[sock]
|
||||
for s in (sock, reverse_sock):
|
||||
if s in self._outgoing:
|
||||
self._outgoing.remove(s)
|
||||
if s in self._incoming:
|
||||
self._incoming.remove(s)
|
||||
if s in self._channel_from_client:
|
||||
self._channel_from_client.remove(s)
|
||||
s.close()
|
||||
del self._channel_init[s]
|
||||
del self._channel_map[s]
|
||||
|
||||
def main():
|
||||
mitm = MicroProxy()
|
||||
mitm.listen(addr='0.0.0.0', port=8080)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class ThreadProxy:
|
||||
wait_symbols = "-\|/"
|
||||
def __init__(
|
||||
self, n_threads_max = 2, buf_byte_size=4096, client_timeout=0.5):
|
||||
self._n_threads = 0
|
||||
self._n_threads_max = n_threads_max
|
||||
self._buf_byte_size = buf_byte_size
|
||||
self._client_timeout = client_timeout
|
||||
|
||||
self._thread_events = []
|
||||
self._threads = []
|
||||
self._job_queue = Queue()
|
||||
self._threads_lock = Lock()
|
||||
self._max_lock = Lock()
|
||||
self._listener_event = Event()
|
||||
self._is_listening = False
|
||||
|
||||
def set_max_thread_count(self, n_threads_max):
|
||||
self._max_lock.acquire()
|
||||
self._n_threads_max = n_threads_max
|
||||
if self._n_threads > self._n_threads_max:
|
||||
self.rescale(self._n_threads_max)
|
||||
self._max_lock.release()
|
||||
|
||||
def max_thread_count(self):
|
||||
return self._n_threads_max
|
||||
|
||||
def thread_count(self):
|
||||
return self._n_threads
|
||||
|
||||
def _get_socket(self):
|
||||
return socket.socket(
|
||||
socket.AF_INET,
|
||||
(
|
||||
socket.SOCK_STREAM
|
||||
if self._proxy_type == "TCP"
|
||||
else
|
||||
socket.SOCK_DGRAM
|
||||
)
|
||||
)
|
||||
|
||||
def _set_listener(self):
|
||||
# Check what kind of socket is needed to
|
||||
# bind onto.
|
||||
# Take the first possible socket and the
|
||||
# required IP info for binding.
|
||||
self._addr_listen = socket.getaddrinfo(
|
||||
self._addr, self._port
|
||||
)[0][-1]
|
||||
|
||||
if hasattr(self, '_socket_listen') and self._socket_listen is not None:
|
||||
self.stop()
|
||||
self._socket_listen = self._get_socket()
|
||||
self._socket_listen.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||
|
||||
def listen(self, addr, port, proxy_type="TCP", backlog=0):
|
||||
if not self._is_listening:
|
||||
self._addr = addr
|
||||
self._port = port
|
||||
self._proxy_type = "UDP" if not proxy_type == "TCP" else proxy_type
|
||||
|
||||
self._set_listener()
|
||||
|
||||
self._socket_listen.bind(self._addr_listen)
|
||||
self._socket_listen.listen(backlog)
|
||||
|
||||
self.rescale(self._n_threads_max)
|
||||
self._listen_thread = Thread(
|
||||
target=self._listener_thread, args=(self._listener_event,)
|
||||
)
|
||||
self._listen_thread.start()
|
||||
print(f"init done for serving on {self._addr_listen}")
|
||||
self._is_listening = True
|
||||
|
||||
def stop(self):
|
||||
if self._is_listening:
|
||||
self._listener_event.set()
|
||||
ctr = 0
|
||||
while self._listen_thread.is_alive():
|
||||
print(
|
||||
(
|
||||
"Waiting for listener thread to finish... "
|
||||
f"{ThreadProxy.wait_symbols[ctr%len(ThreadProxy.wait_symbols)]}\r"
|
||||
),
|
||||
end=""
|
||||
)
|
||||
ctr += 1
|
||||
sleep(0.5)
|
||||
else:
|
||||
print("Listener thread finished closing safely.")
|
||||
self.rescale(0)
|
||||
self._socket_listen.close()
|
||||
del self._listen_thread
|
||||
self._is_listening = False
|
||||
|
||||
def rescale(self, n_threads):
|
||||
new_n_threads = min(
|
||||
(
|
||||
n_threads
|
||||
if isinstance(n_threads, int) and max(-1,n_threads) >= 0
|
||||
else
|
||||
self._n_threads
|
||||
), self._n_threads_max
|
||||
)
|
||||
old_n_threads = self._n_threads
|
||||
if self._n_threads < new_n_threads:
|
||||
self._spin_up(new_n_threads - self._n_threads)
|
||||
elif self._n_threads > new_n_threads:
|
||||
self._spin_down(self._n_threads - new_n_threads)
|
||||
if new_n_threads != old_n_threads:
|
||||
print(
|
||||
"Changed worker thread size "
|
||||
f"from {old_n_threads} to {new_n_threads}."
|
||||
)
|
||||
|
||||
def join(self):
|
||||
if self._is_listening:
|
||||
self._listen_thread.join()
|
||||
|
||||
def _spin_up(self, thread_cnt_new):
|
||||
self._threads_lock.acquire()
|
||||
|
||||
new_thread_events = [
|
||||
Event()
|
||||
for _ in range(thread_cnt_new)
|
||||
]
|
||||
self._thread_events.extend(new_thread_events)
|
||||
|
||||
new_threads = [
|
||||
Thread(target=self._worker_thread, args=(event,))
|
||||
for event in new_thread_events
|
||||
]
|
||||
self._threads.extend(new_threads)
|
||||
self._n_threads = len(self._threads)
|
||||
|
||||
for thread in new_threads:
|
||||
thread.start()
|
||||
|
||||
self._threads_lock.release()
|
||||
|
||||
def _spin_down(self, thread_cnt_del):
|
||||
self._threads_lock.acquire()
|
||||
remaining = self._n_threads - thread_cnt_del
|
||||
|
||||
thread_events_stop = self._thread_events[remaining:]
|
||||
threads_stop = self._threads[remaining:]
|
||||
self._thread_events = self._thread_events[:remaining]
|
||||
self._threads = self._threads[:remaining]
|
||||
for event in thread_events_stop:
|
||||
event.set()
|
||||
|
||||
ctr = 0
|
||||
while any(
|
||||
thread.is_alive()
|
||||
for thread in threads_stop
|
||||
):
|
||||
print(
|
||||
(
|
||||
"Wait for worker threads to finish... "
|
||||
f"{ThreadProxy.wait_symbols[ctr%len(ThreadProxy.wait_symbols)]}\r"
|
||||
),
|
||||
end=""
|
||||
)
|
||||
ctr += 1
|
||||
sleep(0.5)
|
||||
else:
|
||||
print("Worker threads finished spinning down safely.")
|
||||
for idx in range(len(thread_events_stop)-1, -1, -1):
|
||||
del thread_events_stop[idx]
|
||||
del threads_stop[idx]
|
||||
del thread_events_stop
|
||||
del threads_stop
|
||||
|
||||
self._threads_lock.release()
|
||||
|
||||
|
||||
def _listener_thread(self, event):
|
||||
while not event.is_set():
|
||||
conn, addr = self._socket_listen.accept()
|
||||
self._job_queue.put((addr, conn))
|
||||
# clear event to indicate it stopped at spindown task
|
||||
event.clear()
|
||||
|
||||
def init_tunnle(request, sock_in, sock_out, host, port):
|
||||
if request.startswith(b"CONNECT"):
|
||||
try:
|
||||
sock_out.connect((host,port))
|
||||
sock_in.sendall(b"HTTP/1.1 200 established\r\n\r\n")
|
||||
except Exception as e:
|
||||
print("Cannot initiate HTTPS connection:", e)
|
||||
return sock_out, sock_in
|
||||
|
||||
def receive_data(sock, buf_byte):
|
||||
data = b""
|
||||
is_complete = False
|
||||
while not is_complete:
|
||||
try:
|
||||
part_data = sock.recv(buf_byte)
|
||||
if len(part_data) > 0:
|
||||
data += part_data
|
||||
else:
|
||||
is_complete = True
|
||||
except socket.timeout:
|
||||
is_complete = True
|
||||
return data
|
||||
|
||||
def _sendrecv(self, sock_in, sock_out):
|
||||
init_data = ThreadProxy.receive_data(sock_in, self._buf_byte_size)
|
||||
protocol, host_domain, port = ThreadProxy.proxy_forward_filter(init_data.decode())
|
||||
if protocol == "https" or port == 443:
|
||||
sock_out, sock_in = ThreadProxy.init_tunnle(init_data, sock_in, sock_out, host_domain, port)
|
||||
#initial request is CONNECT and handled by init_tunnle
|
||||
is_init = False
|
||||
else:
|
||||
sock_out.connect((host_domain,port))
|
||||
is_init = True
|
||||
is_last_request = len(init_data) == 0
|
||||
|
||||
while not is_last_request:
|
||||
if is_init:
|
||||
request = init_data
|
||||
is_init = False
|
||||
else:
|
||||
request = ThreadProxy.receive_data(sock_in, self._buf_byte_size)
|
||||
if len(request) > 0:
|
||||
sock_out.sendall(request)
|
||||
response = ThreadProxy.receive_data(sock_out, self._buf_byte_size)
|
||||
if len(response) > 0:
|
||||
sock_in.sendall(response)
|
||||
else:
|
||||
is_last_request = True
|
||||
|
||||
def _worker_thread(self, event):
|
||||
print(f"Worker Thread {get_native_id()}: Start working...")
|
||||
while not event.is_set():
|
||||
if not self._job_queue.empty():
|
||||
addr, conn = self._job_queue.get()
|
||||
|
||||
print(f"Worker Thread {get_native_id()}: Handle request of {addr}")
|
||||
|
||||
conn.settimeout(self._client_timeout)
|
||||
socket_client_thread = self._get_socket()
|
||||
socket_client_thread.settimeout(self._client_timeout)
|
||||
try:
|
||||
self._sendrecv(conn, socket_client_thread)
|
||||
except Exception as e:
|
||||
print("ERROR occured in Thread: ", e)
|
||||
conn.close()
|
||||
socket_client_thread.close()
|
||||
else:
|
||||
sleep(0.1)
|
||||
# clear event to indicate it stopped at spindown task
|
||||
event.clear()
|
||||
|
||||
def proxy_forward_filter(request):
|
||||
header = request.split('\n')[0]
|
||||
url = header.split()[1]
|
||||
port = 80
|
||||
protocol = None
|
||||
has_port = False
|
||||
has_protocol = False
|
||||
|
||||
if url.startswith("http"):
|
||||
protocol, host_part = url.split('://')
|
||||
has_protocol = True
|
||||
else:
|
||||
host_part = url
|
||||
|
||||
if ":" in host_part:
|
||||
splitter = host_part.split(':')
|
||||
host_domain = splitter[0]
|
||||
port = int(splitter[1])
|
||||
has_port = True
|
||||
elif "/" in host_part:
|
||||
host_domain = host_part.split('/')[0]
|
||||
|
||||
if not has_protocol and has_port:
|
||||
if port == 443:
|
||||
protocol = "https"
|
||||
else:
|
||||
protocol = "http"
|
||||
if not has_port:
|
||||
if protocol == "https":
|
||||
port = 443
|
||||
else:
|
||||
port = 80
|
||||
return (protocol, host_domain, port)
|
||||
|
||||
def main_alt_thread():
|
||||
mitm = MicroProxy(n_threads_max=20)
|
||||
mitm.listen(addr='0.0.0.0', port=8080)
|
||||
|
140
random_requests.py
Executable file
140
random_requests.py
Executable file
@ -0,0 +1,140 @@
|
||||
import requests
|
||||
from datetime import datetime
|
||||
from random import choices
|
||||
from threading import Thread#
|
||||
from time import sleep
|
||||
from math import sqrt
|
||||
|
||||
def do_request(url_list, count, time_delta, use_proxy=True):
|
||||
global proxies
|
||||
for url in choices(url_list, k=count):
|
||||
kwargs = {'url':url,'proxies':proxies} if use_proxy else {'url':url}
|
||||
start = datetime.now()
|
||||
try:
|
||||
response = requests.get(**kwargs)
|
||||
except Exception as e:
|
||||
print("Some error ...", e)
|
||||
time_delta.append(-1)
|
||||
continue
|
||||
time_diff = datetime.now() - start
|
||||
if response.status_code in (200, '200'):
|
||||
time_delta.append(time_diff)
|
||||
else:
|
||||
time_delta.append(-1)
|
||||
print(f"WARNING for URL '{url}'")
|
||||
|
||||
def do_analysis(url_list, probe_size, thread_count, use_proxy=True):
|
||||
thread_timedeltas = [
|
||||
[]
|
||||
for _ in range(thread_count)
|
||||
]
|
||||
|
||||
threads = [
|
||||
Thread(target=do_request, args=(
|
||||
url_list, probe_size, time_delta, use_proxy
|
||||
))
|
||||
for time_delta in thread_timedeltas
|
||||
]
|
||||
for thread in threads:
|
||||
thread.start()
|
||||
|
||||
wait_string = "-\|/"
|
||||
ctr = 0
|
||||
while any(
|
||||
thread.is_alive()
|
||||
for thread in threads
|
||||
):
|
||||
print(f"Threads are still execution ... {wait_string[ctr%4]}\r", end="")
|
||||
ctr += 1
|
||||
sleep(0.5)
|
||||
print("Finished!", " "*100)
|
||||
|
||||
for idx in range(len(threads)-1,-1,-1):
|
||||
del threads[idx]
|
||||
del threads
|
||||
|
||||
return thread_timedeltas
|
||||
|
||||
|
||||
def do_test(url_list, probe_size, thread_count, use_proxy):
|
||||
thread_timedeltas = do_analysis(url_list, probe_size, thread_count, use_proxy)
|
||||
time_deltas = [
|
||||
[
|
||||
time.total_seconds()
|
||||
for time in time_delta
|
||||
if time != -1
|
||||
]
|
||||
for time_delta in thread_timedeltas
|
||||
]
|
||||
time_delta_values = [val for vals in time_deltas for val in vals]
|
||||
ctr_deltas = len(time_delta_values)
|
||||
min_delta = min(time_delta_values)
|
||||
max_delta = max(time_delta_values)
|
||||
avg_delta = sum(time_delta_values)/ctr_deltas
|
||||
err_delta = (thread_count * probe_size) - ctr_deltas
|
||||
std_delta = sqrt(sum( (delta-avg_delta)**2 for delta in time_delta_values)/(ctr_deltas-1))
|
||||
sort_delta = sorted(time_delta_values)
|
||||
med_delta = sort_delta[(ctr_deltas-1)//2]
|
||||
if len(time_delta_values) % 2 == 0:
|
||||
med_delta = (med_delta + sort_delta[(ctr_deltas)//2])/2
|
||||
|
||||
result = (min_delta, med_delta, avg_delta, max_delta, std_delta, err_delta)
|
||||
return result
|
||||
|
||||
|
||||
|
||||
### INIT GET VALUES ###########################################################
|
||||
proxy_file_mappings = {
|
||||
#"rpi-compute": "rpi-4",
|
||||
#"rpi-proxy2": "rpi-2",
|
||||
"rpi-proxy0": "rpi-0",
|
||||
"94.2.18.222": "rpi-pico"
|
||||
}
|
||||
|
||||
|
||||
random_links_file = "/home/lhahn/Projekte/pico-test/random_wiki_links.txt"
|
||||
with open(random_links_file, "r") as file:
|
||||
link_list = [
|
||||
line.rstrip()
|
||||
for line in file
|
||||
if len(line.rstrip()) > 0
|
||||
]
|
||||
|
||||
allfile = open("/home/lhahn/Projekte/pico-test/results_rpi-proxies.txt","a")
|
||||
#allfile.write("rpi\tproxy\tprobesize\tthreads\tmin(s)\tmed(s)\tavg(s)\tmax(s)\tsd(s)\terr\n")
|
||||
first_round = False
|
||||
### ANALYSIS DONE IN SEVERAL CONFIGS ##########################################
|
||||
for proxy,filename in proxy_file_mappings.items():
|
||||
proxies = {
|
||||
'http': f'http://{proxy}:8080',
|
||||
'https': f'http://{proxy}:8080'
|
||||
}
|
||||
with open(f"/home/lhahn/Projekte/pico-test/results_{filename}-proxy.txt", "w") as f:
|
||||
f.write("proxy\tprobesize\tthreads\tmin(s)\tmed(s)\tavg(s)\tmax(s)\tsd(s)\terr\n")
|
||||
for use_proxy in (False, True):
|
||||
for probe_size in (10,25,50,100):
|
||||
for thread_count in (1,5,10,20):
|
||||
min_delta, med_delta, avg_delta, max_delta, std_delta, err_delta = do_test(
|
||||
link_list, probe_size, thread_count, use_proxy
|
||||
)
|
||||
data_str = (
|
||||
f"{use_proxy}\t{probe_size}\t{thread_count}\t{min_delta}\t{med_delta}"
|
||||
f"\t{avg_delta}\t{max_delta}\t{std_delta}\t{err_delta}\n"
|
||||
)
|
||||
result_str = (
|
||||
f"avg: {avg_delta}s, med:{med_delta} min: {min_delta}s, max: {max_delta}s, "
|
||||
f"std: {std_delta}s | err: {err_delta}/{probe_size*thread_count} | "
|
||||
f"thrds: {thread_count}, proxy: {use_proxy}, probe_size: {probe_size}, "
|
||||
f"rpi: {filename}"
|
||||
)
|
||||
print(result_str)
|
||||
|
||||
f.write(data_str)
|
||||
f.flush()
|
||||
if use_proxy or (not use_proxy and first_round):
|
||||
allfile.write(
|
||||
f"{filename}\t{data_str}"
|
||||
)
|
||||
allfile.flush()
|
||||
first_round = False
|
||||
allfile.close()
|
51
random_wiki_links.txt
Executable file
51
random_wiki_links.txt
Executable file
@ -0,0 +1,51 @@
|
||||
https://en.wikipedia.org/wiki/Intertemporal_budget_constraint
|
||||
https://en.wikipedia.org/wiki/Martin_Bell_(archaeologist)
|
||||
https://en.wikipedia.org/wiki/Anna_Hannevik
|
||||
https://en.wikipedia.org/wiki/Warm_Springs,_Montana
|
||||
https://en.wikipedia.org/wiki/Automated_optical_inspection
|
||||
https://en.wikipedia.org/wiki/Aunt_Sammy
|
||||
https://en.wikipedia.org/wiki/1993_in_Norwegian_football
|
||||
https://en.wikipedia.org/wiki/Michael_Paterson
|
||||
https://en.wikipedia.org/wiki/Perfecto_de_Castro
|
||||
https://en.wikipedia.org/wiki/Joco_(disambiguation)
|
||||
https://en.wikipedia.org/wiki/TP_Ostrovia_Ostr%C3%B3w_Wielkopolski
|
||||
https://en.wikipedia.org/wiki/Bautista,_Pangasinan
|
||||
https://en.wikipedia.org/wiki/Pedro_Taborda
|
||||
https://en.wikipedia.org/wiki/Samuel_Kettell
|
||||
https://en.wikipedia.org/wiki/Trachysomus_wappesi
|
||||
https://en.wikipedia.org/wiki/Mordellistena_louisianae
|
||||
https://en.wikipedia.org/wiki/Peter_Wellings
|
||||
https://en.wikipedia.org/wiki/COVID-19_pandemic_in_Taiwan
|
||||
https://en.wikipedia.org/wiki/Prunus_mexicana
|
||||
https://en.wikipedia.org/wiki/Matt_Foster
|
||||
https://en.wikipedia.org/wiki/Lindsay_Vaughn
|
||||
https://en.wikipedia.org/wiki/List_of_Indo-Guyanese_people
|
||||
https://en.wikipedia.org/wiki/Krasnoufimsky_District
|
||||
https://en.wikipedia.org/wiki/2015%E2%80%9316_SKNFA_Super_League
|
||||
https://en.wikipedia.org/wiki/George_Richmond_Grose
|
||||
https://en.wikipedia.org/wiki/Stawell_railway_station
|
||||
https://en.wikipedia.org/wiki/Devonshire_Dock_Hall
|
||||
https://en.wikipedia.org/wiki/Chakhar_Chamani
|
||||
https://en.wikipedia.org/wiki/List_of_listed_buildings_in_Saline,_Fife
|
||||
https://en.wikipedia.org/wiki/Chitala
|
||||
https://en.wikipedia.org/wiki/Ouachita_Avenue_Historic_District
|
||||
https://en.wikipedia.org/wiki/Vehicle_registration_plates_of_Guyana
|
||||
https://en.wikipedia.org/wiki/Antonio_French
|
||||
https://en.wikipedia.org/wiki/Odontocera_hirundipennis
|
||||
https://en.wikipedia.org/wiki/Culver_Ridge
|
||||
https://en.wikipedia.org/wiki/Eordaia
|
||||
https://en.wikipedia.org/wiki/NER_Class_X
|
||||
https://en.wikipedia.org/wiki/Darreh_Bang_Rugardengah
|
||||
https://en.wikipedia.org/wiki/Pandin
|
||||
https://en.wikipedia.org/wiki/Wells,_Maine
|
||||
https://en.wikipedia.org/wiki/Cottonera_Lines
|
||||
https://en.wikipedia.org/wiki/A_Pinch_of_Snuff_(novel)
|
||||
https://en.wikipedia.org/wiki/B%C3%A0u_Chinh
|
||||
https://en.wikipedia.org/wiki/Saint-Maurice-des-Champs
|
||||
https://en.wikipedia.org/wiki/Cheer_Up,_Mr._Lee
|
||||
https://en.wikipedia.org/wiki/Downtown_Owl_(film)
|
||||
https://en.wikipedia.org/wiki/2015_Copa_Libertadores_second_stage
|
||||
https://en.wikipedia.org/wiki/2014%E2%80%9315_Czech_First_League
|
||||
https://en.wikipedia.org/wiki/Air_Surveillance_Wing_(Estonia)
|
||||
https://en.wikipedia.org/wiki/Rice_County,_Kansas
|
||||
|
0
readme.txt
Executable file
0
readme.txt
Executable file
33
results_rpi-0-proxy.txt
Executable file
33
results_rpi-0-proxy.txt
Executable file
@ -0,0 +1,33 @@
|
||||
proxy probesize threads min(s) med(s) avg(s) max(s) sd(s) err
|
||||
False 10 1 0.046536 0.061677 0.0752834 0.21199 0.04892309682711792 0
|
||||
False 10 5 0.044171 0.060025499999999996 0.06250002 0.109824 0.011338603568215217 0
|
||||
False 10 10 0.045522 0.062883 0.06292447999999998 0.109325 0.009743953590060481 0
|
||||
False 10 20 0.044138 0.06716050000000001 0.06684208000000003 0.115662 0.011931403712739834 0
|
||||
False 25 1 0.04307 0.060673 0.06206852 0.096587 0.013129487439602001 0
|
||||
False 25 5 0.042116 0.058163 0.06114224000000001 0.116519 0.011564586651748796 0
|
||||
False 25 10 0.041396 0.0629185 0.063441276 0.118276 0.01109555244447144 0
|
||||
False 25 20 0.044908 0.065925 0.06736639400000004 0.125421 0.01085174532284405 0
|
||||
False 50 1 0.044012 0.060331499999999996 0.0619153 0.110889 0.012387670116214883 0
|
||||
False 50 5 0.041966 0.0608965 0.06310128400000004 0.124835 0.012223720540438857 0
|
||||
False 50 10 0.043802 0.06290899999999999 0.06402033600000004 0.120987 0.011086957378782594 0
|
||||
False 50 20 0.043818 0.06528700000000001 0.06682387600000013 0.141692 0.012191870504603682 0
|
||||
False 100 1 0.043002 0.062425499999999995 0.06219341000000002 0.097122 0.010317976518497345 0
|
||||
False 100 5 0.042899 0.0624985 0.06292142799999999 0.122822 0.010043609624502273 0
|
||||
False 100 10 0.042548 0.0633605 0.06374070699999997 0.126233 0.010756968706513182 0
|
||||
False 100 20 0.043454 0.0654035 0.06684689049999999 0.138428 0.012347454857064014 0
|
||||
True 10 1 0.470139 0.9776290000000001 1.05756925 2.172159 0.5680755245047591 2
|
||||
True 10 5 0.487766 0.9305915 1.1440171 7.760909 1.0792800729053518 0
|
||||
True 10 10 0.408449 1.011827 1.720413727272727 38.687804 3.9771223157497753 1
|
||||
True 10 20 0.435667 1.4465919999999999 2.9104563349999997 34.889739 4.464876392627195 0
|
||||
True 25 1 0.263529 0.624963 0.6393519199999999 1.025937 0.1764719008413993 0
|
||||
True 25 5 0.425042 1.067067 1.176152248 3.247047 0.4593388904120203 0
|
||||
True 25 10 0.40333 0.8429534999999999 1.917743850806453 68.853489 5.773668797468752 2
|
||||
True 25 20 0.118881 1.1690755 1.9691684000000003 73.249322 4.440429642600693 10
|
||||
True 50 1 0.378436 0.6261215 0.6401591000000001 1.429998 0.16768655754628783 0
|
||||
True 50 5 0.140034 0.957948 1.189219919354839 12.061802 1.2709049157107513 2
|
||||
True 50 10 0.106731 1.118524 1.6789639919839705 17.305791 2.0091832750543768 1
|
||||
True 50 20 0.37752 1.4820259999999998 2.9884222323943637 66.253599 5.340589560842322 6
|
||||
True 100 1 0.279229 0.581473 0.5935158899999999 1.127414 0.13501656527876363 0
|
||||
True 100 5 0.399367 0.9562660000000001 1.1202544459999995 4.722667 0.5483744036240559 0
|
||||
True 100 10 0.355105 1.275188 1.8825838221105529 32.948261 2.172760972791116 5
|
||||
True 100 20 0.343612 1.344229 2.2484285411408367 73.176475 4.620196513875076 19
|
33
results_rpi-2-proxy.txt
Executable file
33
results_rpi-2-proxy.txt
Executable file
@ -0,0 +1,33 @@
|
||||
proxy probesize threads min(s) med(s) avg(s) max(s) sd(s) err
|
||||
False 10 1 0.049546 0.0653085 0.07603079999999998 0.199493 0.04404371009147869 0
|
||||
False 10 5 0.045464 0.0650185 0.06628247999999998 0.114825 0.01411616572678723 0
|
||||
False 10 10 0.048 0.0643875 0.06524180999999998 0.126871 0.012394218534653466 0
|
||||
False 10 20 0.04621 0.06373799999999999 0.06512516000000002 0.117645 0.010342864468874545 0
|
||||
False 25 1 0.051174 0.065948 0.06405403999999999 0.076878 0.007594675741816324 0
|
||||
False 25 5 0.045273 0.061257 0.06421200799999999 0.126283 0.014068929745557028 0
|
||||
False 25 10 0.043393 0.063708 0.064355296 0.120371 0.011935442577065405 0
|
||||
False 25 20 0.044336 0.065109 0.066328148 0.138949 0.011817500297298467 0
|
||||
False 50 1 0.048006 0.0636265 0.0643729 0.12306 0.012412380209258162 0
|
||||
False 50 5 0.042417 0.06325800000000001 0.063484904 0.113597 0.011233843571473539 0
|
||||
False 50 10 0.042024 0.06276200000000001 0.06334417 0.122368 0.010571227908814576 0
|
||||
False 50 20 0.043562 0.06478600000000001 0.06637446299999993 0.139304 0.01129278563065512 0
|
||||
False 100 1 0.043471 0.062607 0.06453615 0.114254 0.013829495429181696 0
|
||||
False 100 5 0.041149 0.062817 0.06378914600000005 0.122499 0.011648234664113896 0
|
||||
False 100 10 0.041935 0.0627375 0.06360931000000002 0.123082 0.010711365194139458 0
|
||||
False 100 20 0.045126 0.065891 0.06705012200000006 0.14236 0.011524006370378684 0
|
||||
True 10 1 0.082593 0.091895 0.0933129 0.113011 0.010213139113144618 0
|
||||
True 10 5 0.071026 0.1061995 0.21161528000000004 1.135839 0.2810332008110858 0
|
||||
True 10 10 0.070867 0.129955 0.3081397900000001 1.973437 0.4357660019152921 0
|
||||
True 10 20 0.072841 0.1260475 0.4945304099999999 14.406155 1.4045274907784335 0
|
||||
True 25 1 0.080716 0.092062 0.09508203999999999 0.133946 0.013216435265355531 0
|
||||
True 25 5 0.069939 0.111354 0.20515491199999997 1.171152 0.2797495376408879 0
|
||||
True 25 10 0.076486 0.114143 0.26257808800000004 7.583448 0.7163466317882828 0
|
||||
True 25 20 0.080446 0.135388 0.573287568 54.520381 2.893917844544734 0
|
||||
True 50 1 0.073323 0.0933065 0.09513179999999999 0.134943 0.01286588577024766 0
|
||||
True 50 5 0.0684 0.10697 0.18744250799999992 1.352011 0.2634756590900604 0
|
||||
True 50 10 0.07642 0.13082500000000002 0.28653655600000016 3.32304 0.47890398305845555 0
|
||||
True 50 20 0.065947 0.14079599999999998 0.45855420799999974 20.562857 1.3681876872329788 0
|
||||
True 100 1 0.064478 0.0938725 0.09880818 0.188272 0.018865169940834498 0
|
||||
True 100 5 0.071009 0.1527185 0.22219954400000033 1.385164 0.23665895880128826 0
|
||||
True 100 10 0.066571 0.1772145 0.3431166930000004 15.582992 0.701055150887099 0
|
||||
True 100 20 0.076804 0.174723 0.5054862751375695 31.828925 1.4606876640694766 1
|
33
results_rpi-4-proxy.txt
Executable file
33
results_rpi-4-proxy.txt
Executable file
@ -0,0 +1,33 @@
|
||||
proxy probesize threads min(s) med(s) avg(s) max(s) sd(s) err
|
||||
False 10 1 0.05258 0.063268 0.06401799999999999 0.082845 0.009716211447312625 0
|
||||
False 10 5 0.042688 0.0663445 0.06621266 0.116224 0.01346127034004425 0
|
||||
False 10 10 0.045348 0.062815 0.06432804999999997 0.116481 0.010837762825328888 0
|
||||
False 10 20 0.044482 0.064625 0.06609842000000006 0.131521 0.012003280662255818 0
|
||||
False 25 1 0.043608 0.060865 0.06101180000000001 0.076343 0.010558069567870825 0
|
||||
False 25 5 0.043438 0.06687 0.06542612000000002 0.120313 0.0115352178822215 0
|
||||
False 25 10 0.042775 0.064003 0.071858768 0.319419 0.04381362842286042 0
|
||||
False 25 20 0.044654 0.0655105 0.06718682199999998 0.133067 0.012855381613439963 0
|
||||
False 50 1 0.04533 0.064195 0.06420501999999999 0.08196 0.009165501412495064 0
|
||||
False 50 5 0.04235 0.0613085 0.06369152000000003 0.128451 0.01253812076808884 0
|
||||
False 50 10 0.042324 0.0637185 0.06425232800000001 0.120578 0.011820002484851676 0
|
||||
False 50 20 0.044236 0.0654525 0.0669509129999999 0.129377 0.01116333680572566 0
|
||||
False 100 1 0.044904 0.060164499999999996 0.06269716 0.121312 0.012338375918960151 0
|
||||
False 100 5 0.043138 0.0612435 0.06285398799999996 0.124611 0.011235806510604546 0
|
||||
False 100 10 0.042357 0.062998 0.06379597200000006 0.128426 0.011318821297236506 0
|
||||
False 100 20 0.042693 0.0660605 0.06729693049999994 0.140146 0.011620403794052865 0
|
||||
True 10 1 0.078209 0.088172 0.11936390000000001 0.397408 0.09805119093893987 0
|
||||
True 10 5 0.071983 0.0960995 0.17419723999999992 1.53029 0.29362031027777125 0
|
||||
True 10 10 0.07185 0.1047775 0.2683098399999999 2.788466 0.49892228717301645 0
|
||||
True 10 20 0.074289 0.1052255 0.8091272950000004 53.112468 4.383652551157289 0
|
||||
True 25 1 0.073915 0.085645 0.08659704000000001 0.12133 0.010799185364646724 0
|
||||
True 25 5 0.072272 0.10204 0.139369 1.367289 0.19369664094923308 0
|
||||
True 25 10 0.069689 0.11056350000000001 0.21563888399999986 4.465215 0.47754047078931156 0
|
||||
True 25 20 0.071833 0.12436050000000001 0.3836931559999997 15.472908 1.1340368640483225 0
|
||||
True 50 1 0.071639 0.0826635 0.08565465999999997 0.127944 0.012000784504305355 0
|
||||
True 50 5 0.063988 0.10142200000000001 0.1466366 3.160849 0.2453367643449244 0
|
||||
True 50 10 0.068776 0.1124955 0.2135674820000001 7.373921 0.5492528008569718 0
|
||||
True 50 20 0.057859 0.112275 0.3703267887887888 54.392447 2.33174245914143 1
|
||||
True 100 1 0.07133 0.08601500000000001 0.09002922000000008 0.171554 0.019164358265511765 0
|
||||
True 100 5 0.060425 0.10495 0.14636869800000002 1.21535 0.19144504160574558 0
|
||||
True 100 10 0.057269 0.117783 0.22751823699999982 7.286814 0.46211266535896617 0
|
||||
True 100 20 0.063147 0.124401 0.3515133696848417 55.451408 1.7760218566214225 1
|
18
results_rpi-pico-proxy.txt
Executable file
18
results_rpi-pico-proxy.txt
Executable file
@ -0,0 +1,18 @@
|
||||
proxy probesize threads min(s) med(s) avg(s) max(s) sd(s) err
|
||||
False 10 1 0.048808 0.07022300000000001 0.07672659999999998 0.164185 0.03200964279088413 0
|
||||
False 10 5 0.042816 0.062145 0.06268869999999999 0.11818 0.012464839753957398 0
|
||||
False 10 10 0.04377 0.06651099999999999 0.06536197000000003 0.106091 0.0103605000127524 0
|
||||
False 10 20 0.046672 0.06454299999999999 0.06551675500000004 0.12511 0.010680802788931892 0
|
||||
False 25 1 0.042986 0.064072 0.06375331999999999 0.087259 0.009216086957597567 0
|
||||
False 25 5 0.042791 0.063396 0.06423262400000002 0.12126 0.012092473756808273 0
|
||||
False 25 10 0.045328 0.06397 0.06519232400000004 0.122583 0.012130780239700979 0
|
||||
False 25 20 0.044618 0.06596650000000001 0.06687705000000001 0.130979 0.01163324345356875 0
|
||||
False 50 1 0.042629 0.06450349999999999 0.06401042 0.116855 0.013042292760579064 0
|
||||
False 50 5 0.043338 0.061895 0.063225352 0.122865 0.011386014738202752 0
|
||||
False 50 10 0.04348 0.063362 0.06381445799999994 0.124387 0.011777126692810643 0
|
||||
False 50 20 0.043025 0.06498 0.06623561 0.138012 0.011070506585606729 0
|
||||
False 100 1 0.04209 0.062305 0.06319001 0.111031 0.011515743188423282 0
|
||||
False 100 5 0.042515 0.063029 0.06356240399999996 0.124533 0.011557744523119872 0
|
||||
False 100 10 0.041643 0.063434 0.06410064999999998 0.296015 0.013086469614853368 0
|
||||
False 100 20 0.043326 0.06589149999999999 0.06913456299999998 0.199696 0.018131998587646737 0
|
||||
True 10 1 2.373214 3.485658 4.0446436 9.595809 2.21955089424551 0
|
66
results_rpi-proxies.txt
Executable file
66
results_rpi-proxies.txt
Executable file
@ -0,0 +1,66 @@
|
||||
rpi proxy probesize threads min(s) med(s) avg(s) max(s) sd(s) err
|
||||
PC False 10 1 0.047994 0.068465 0.0641226 0.076412 0.00997050435813332 0
|
||||
PC False 10 5 0.042907 0.0621605 0.06177637999999999 0.07904 0.00913705761795763 0
|
||||
PC False 10 10 0.045021 0.0625115 0.06314348000000002 0.114743 0.009697101832459577 0
|
||||
PC False 10 20 0.045928 0.064854 0.06615820500000001 0.131961 0.013274161851025135 0
|
||||
PC False 25 1 0.047917 0.067809 0.06485632 0.097195 0.010472119372091465 0
|
||||
PC False 25 5 0.042642 0.067011 0.064889376 0.092108 0.009833453011206843 0
|
||||
PC False 25 10 0.043023 0.0617315 0.06389453599999997 0.114211 0.010948782880437253 0
|
||||
PC False 25 20 0.045483 0.0658605 0.06693427800000008 0.114855 0.011041971881996515 0
|
||||
PC False 50 1 0.04415 0.06783349999999999 0.06756248000000001 0.116407 0.0145781397055695 0
|
||||
PC False 50 5 0.044018 0.061857499999999996 0.06300734399999999 0.120387 0.01044973487959764 0
|
||||
PC False 50 10 0.041109 0.0628705 0.06405227600000003 0.122661 0.011921940694352713 0
|
||||
PC False 50 20 0.042441 0.06539500000000001 0.06702196199999993 0.143467 0.012588986843280763 0
|
||||
PC False 100 1 0.043411 0.0599915 0.06288284999999999 0.123584 0.014168585276408107 0
|
||||
PC False 100 5 0.042401 0.0642625 0.06562582 0.294081 0.0227362529373435 0
|
||||
PC False 100 10 0.042718 0.06338099999999999 0.06376098500000005 0.124887 0.011260088078621472 0
|
||||
PC False 100 20 0.043766 0.066694 0.06886808450000007 0.296573 0.016201935733427503 0
|
||||
rpi-4 True 10 1 0.078209 0.088172 0.11936390000000001 0.397408 0.09805119093893987 0
|
||||
rpi-4 True 10 5 0.071983 0.0960995 0.17419723999999992 1.53029 0.29362031027777125 0
|
||||
rpi-4 True 10 10 0.07185 0.1047775 0.2683098399999999 2.788466 0.49892228717301645 0
|
||||
rpi-4 True 10 20 0.074289 0.1052255 0.8091272950000004 53.112468 4.383652551157289 0
|
||||
rpi-4 True 25 1 0.073915 0.085645 0.08659704000000001 0.12133 0.010799185364646724 0
|
||||
rpi-4 True 25 5 0.072272 0.10204 0.139369 1.367289 0.19369664094923308 0
|
||||
rpi-4 True 25 10 0.069689 0.11056350000000001 0.21563888399999986 4.465215 0.47754047078931156 0
|
||||
rpi-4 True 25 20 0.071833 0.12436050000000001 0.3836931559999997 15.472908 1.1340368640483225 0
|
||||
rpi-4 True 50 1 0.071639 0.0826635 0.08565465999999997 0.127944 0.012000784504305355 0
|
||||
rpi-4 True 50 5 0.063988 0.10142200000000001 0.1466366 3.160849 0.2453367643449244 0
|
||||
rpi-4 True 50 10 0.068776 0.1124955 0.2135674820000001 7.373921 0.5492528008569718 0
|
||||
rpi-4 True 50 20 0.057859 0.112275 0.3703267887887888 54.392447 2.33174245914143 1
|
||||
rpi-4 True 100 1 0.07133 0.08601500000000001 0.09002922000000008 0.171554 0.019164358265511765 0
|
||||
rpi-4 True 100 5 0.060425 0.10495 0.14636869800000002 1.21535 0.19144504160574558 0
|
||||
rpi-4 True 100 10 0.057269 0.117783 0.22751823699999982 7.286814 0.46211266535896617 0
|
||||
rpi-4 True 100 20 0.063147 0.124401 0.3515133696848417 55.451408 1.7760218566214225 1
|
||||
rpi-2 True 10 1 0.082593 0.091895 0.0933129 0.113011 0.010213139113144618 0
|
||||
rpi-2 True 10 5 0.071026 0.1061995 0.21161528000000004 1.135839 0.2810332008110858 0
|
||||
rpi-2 True 10 10 0.070867 0.129955 0.3081397900000001 1.973437 0.4357660019152921 0
|
||||
rpi-2 True 10 20 0.072841 0.1260475 0.4945304099999999 14.406155 1.4045274907784335 0
|
||||
rpi-2 True 25 1 0.080716 0.092062 0.09508203999999999 0.133946 0.013216435265355531 0
|
||||
rpi-2 True 25 5 0.069939 0.111354 0.20515491199999997 1.171152 0.2797495376408879 0
|
||||
rpi-2 True 25 10 0.076486 0.114143 0.26257808800000004 7.583448 0.7163466317882828 0
|
||||
rpi-2 True 25 20 0.080446 0.135388 0.573287568 54.520381 2.893917844544734 0
|
||||
rpi-2 True 50 1 0.073323 0.0933065 0.09513179999999999 0.134943 0.01286588577024766 0
|
||||
rpi-2 True 50 5 0.0684 0.10697 0.18744250799999992 1.352011 0.2634756590900604 0
|
||||
rpi-2 True 50 10 0.07642 0.13082500000000002 0.28653655600000016 3.32304 0.47890398305845555 0
|
||||
rpi-2 True 50 20 0.065947 0.14079599999999998 0.45855420799999974 20.562857 1.3681876872329788 0
|
||||
rpi-2 True 100 1 0.064478 0.0938725 0.09880818 0.188272 0.018865169940834498 0
|
||||
rpi-2 True 100 5 0.071009 0.1527185 0.22219954400000033 1.385164 0.23665895880128826 0
|
||||
rpi-2 True 100 10 0.066571 0.1772145 0.3431166930000004 15.582992 0.701055150887099 0
|
||||
rpi-2 True 100 20 0.076804 0.174723 0.5054862751375695 31.828925 1.4606876640694766 1
|
||||
rpi-0 True 10 1 0.470139 0.9776290000000001 1.05756925 2.172159 0.5680755245047591 2
|
||||
rpi-0 True 10 5 0.487766 0.9305915 1.1440171 7.760909 1.0792800729053518 0
|
||||
rpi-0 True 10 10 0.408449 1.011827 1.720413727272727 38.687804 3.9771223157497753 1
|
||||
rpi-0 True 10 20 0.435667 1.4465919999999999 2.9104563349999997 34.889739 4.464876392627195 0
|
||||
rpi-0 True 25 1 0.263529 0.624963 0.6393519199999999 1.025937 0.1764719008413993 0
|
||||
rpi-0 True 25 5 0.425042 1.067067 1.176152248 3.247047 0.4593388904120203 0
|
||||
rpi-0 True 25 10 0.40333 0.8429534999999999 1.917743850806453 68.853489 5.773668797468752 2
|
||||
rpi-0 True 25 20 0.118881 1.1690755 1.9691684000000003 73.249322 4.440429642600693 10
|
||||
rpi-0 True 50 1 0.378436 0.6261215 0.6401591000000001 1.429998 0.16768655754628783 0
|
||||
rpi-0 True 50 5 0.140034 0.957948 1.189219919354839 12.061802 1.2709049157107513 2
|
||||
rpi-0 True 50 10 0.106731 1.118524 1.6789639919839705 17.305791 2.0091832750543768 1
|
||||
rpi-0 True 50 20 0.37752 1.4820259999999998 2.9884222323943637 66.253599 5.340589560842322 6
|
||||
rpi-0 True 100 1 0.279229 0.581473 0.5935158899999999 1.127414 0.13501656527876363 0
|
||||
rpi-0 True 100 5 0.399367 0.9562660000000001 1.1202544459999995 4.722667 0.5483744036240559 0
|
||||
rpi-0 True 100 10 0.355105 1.275188 1.8825838221105529 32.948261 2.172760972791116 5
|
||||
rpi-0 True 100 20 0.343612 1.344229 2.2484285411408367 73.176475 4.620196513875076 19
|
||||
rpi-pico True 10 1 2.373214 3.485658 4.0446436 9.595809 2.21955089424551 0
|
94
simple_server.py
Executable file
94
simple_server.py
Executable file
@ -0,0 +1,94 @@
|
||||
import time
|
||||
import network
|
||||
import socket
|
||||
import machine
|
||||
|
||||
from machine import Pin
|
||||
|
||||
intled = machine.Pin("LED", machine.Pin.OUT)
|
||||
|
||||
ssid = 'Lars-WLAN'
|
||||
password = '0243LHBS18021909'
|
||||
|
||||
wlan = network.WLAN(network.STA_IF)
|
||||
wlan.active(True)
|
||||
wlan.connect(ssid, password)
|
||||
|
||||
html = """<!DOCTYPE html>
|
||||
<html>
|
||||
<head> <title>Pico W</title> </head>
|
||||
<body> <h1>Pico W</h1>
|
||||
<p>Hello World</p>
|
||||
<p>
|
||||
<a href='/light/on'>Turn Light On</a>
|
||||
</p>
|
||||
<p>
|
||||
<a href='/light/off'>Turn Light Off</a>
|
||||
</p>
|
||||
<br>
|
||||
</body>
|
||||
</html>
|
||||
"""
|
||||
|
||||
# Wait for connect or fail
|
||||
max_wait = 10
|
||||
while max_wait > 0:
|
||||
if wlan.status() < 0 or wlan.status() >= 3:
|
||||
break
|
||||
max_wait -= 1
|
||||
print('waiting for connection...')
|
||||
time.sleep(1)
|
||||
|
||||
# Handle connection error
|
||||
if wlan.status() != 3:
|
||||
raise RuntimeError('network connection failed')
|
||||
else:
|
||||
print('connected')
|
||||
status = wlan.ifconfig()
|
||||
print( 'ip = ' + status[0] )
|
||||
|
||||
# Open socket
|
||||
addr = socket.getaddrinfo('0.0.0.0', 80)[0][-1]
|
||||
|
||||
s = socket.socket()
|
||||
s.bind(addr)
|
||||
s.listen(1)
|
||||
|
||||
print('listening on', addr)
|
||||
|
||||
stateis = ""
|
||||
|
||||
# Listen for connections
|
||||
while True:
|
||||
try:
|
||||
cl, addr = s.accept()
|
||||
print('client connected from', addr)
|
||||
|
||||
request = cl.recv(1024)
|
||||
print(request)
|
||||
|
||||
request = str(request)
|
||||
led_on = request.find('/light/on')
|
||||
led_off = request.find('/light/off')
|
||||
print( 'led on = ' + str(led_on))
|
||||
print( 'led off = ' + str(led_off))
|
||||
|
||||
if led_on == 6:
|
||||
print("led on")
|
||||
intled.value(1)
|
||||
stateis = "LED is ON"
|
||||
|
||||
if led_off == 6:
|
||||
print("led off")
|
||||
intled.value(0)
|
||||
stateis = "LED is OFF"
|
||||
|
||||
response = html + stateis
|
||||
|
||||
cl.send('HTTP/1.0 200 OK\r\nContent-type: text/html\r\n\r\n')
|
||||
cl.send(response)
|
||||
cl.close()
|
||||
|
||||
except OSError as e:
|
||||
cl.close()
|
||||
print('connection closed')
|
106
wlan_scan.py
Executable file
106
wlan_scan.py
Executable file
@ -0,0 +1,106 @@
|
||||
import logging
|
||||
import network
|
||||
import binascii
|
||||
import machine
|
||||
from math import sqrt
|
||||
|
||||
|
||||
class WlanSniffer:
|
||||
def fibonacci_n(n):
|
||||
fivesqrt = sqrt(5)
|
||||
return int((((1+fivesqrt)/2)**n-((1-fivesqrt)/2)**n)/fivesqrt)
|
||||
|
||||
def __init__(self, led_pin="LED", retry_limit=0, logger=None):
|
||||
self.led = machine.Pin(led_pin, machine.Pin.OUT)
|
||||
self.wlan = network.WLAN(network.STA_IF)
|
||||
self.detected_wlans = {}
|
||||
self.retry_limit = 1 if retry_limit == 0 else retry_limit
|
||||
self.fibonacci = retry_limit == 0
|
||||
self.logger = logger if logger is not None else logging.getLogger()
|
||||
|
||||
self.wlan.active(True)
|
||||
|
||||
|
||||
def _update_retry_limit(self, round):
|
||||
return (
|
||||
WlanSniffer.fibonacci_n(round)
|
||||
if self.fibonacci
|
||||
else
|
||||
self.retry_limit
|
||||
)
|
||||
|
||||
|
||||
def w_led_on(self):
|
||||
self.led.value(1)
|
||||
|
||||
|
||||
def w_led_off(self):
|
||||
self.led.value(0)
|
||||
|
||||
|
||||
def get_sniffed_wlans(self):
|
||||
return dict(self.detected_wlans)
|
||||
|
||||
|
||||
def sniff(self):
|
||||
retry_limit = self.retry_limit
|
||||
found_round = 0
|
||||
retry = 0
|
||||
|
||||
self.w_led_on()
|
||||
|
||||
while retry != retry_limit:
|
||||
self.logger.debug(f"Retry {retry}")
|
||||
found_wlans = self.wlan.scan()
|
||||
retry += 1
|
||||
detected = False
|
||||
|
||||
for found_wlan in found_wlans:
|
||||
ssid, bssid, channel, RSSI, security, hidden = found_wlan
|
||||
ssid = ssid.decode('utf-8')
|
||||
bssid = binascii.hexlify(bssid).decode()
|
||||
if ssid not in self.detected_wlans.keys():
|
||||
self.detected_wlans[ssid] = {
|
||||
"ssid": ssid,
|
||||
"bssid": [bssid],
|
||||
"channel": channel,
|
||||
"rssi": RSSI,
|
||||
"security": security,
|
||||
"hidden": hidden,
|
||||
"order_found": found_round
|
||||
}
|
||||
self.logger.info(f"NEW WLAN: {self.detected_wlans[ssid]}")
|
||||
detected = True
|
||||
elif bssid not in self.detected_wlans[ssid]['bssid']:
|
||||
self.logger.info(f"NEW BSSID: {bssid} for WLAN '{ssid}'")
|
||||
self.detected_wlans[ssid]['bssid'].append(bssid)
|
||||
if detected:
|
||||
found_round += 1
|
||||
old_retry_limit = retry_limit
|
||||
retry_limit = self._update_retry_limit(found_round)
|
||||
self.logger.debug(f"Set retry limit from {old_retry_limit} to {retry_limit}")
|
||||
detected = False
|
||||
retry = 0
|
||||
self.w_led_off()
|
||||
|
||||
|
||||
def main():
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
log = logging.getLogger("WlanSniffer")
|
||||
sniffer = WlanSniffer(logger=log)
|
||||
sniffer.sniff()
|
||||
wlans = sniffer.get_sniffed_wlans()
|
||||
|
||||
with open("sniffed_wlans.txt", "w") as file:
|
||||
for wlan in wlans.values():
|
||||
line = ", ".join(
|
||||
f"{str(k)}:{str(v)}"
|
||||
for k,v in wlan.items()
|
||||
)
|
||||
log.info(f"Found WLAN: {line}")
|
||||
print(f"Found WLAN: {line}")
|
||||
file.write(f"{line}\n")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
Loading…
Reference in New Issue
Block a user