we now have two way communication

This commit is contained in:
Kevin Froman 2020-04-20 03:36:41 -05:00
parent 0a0de1c7b0
commit 837caa17e0
10 changed files with 277 additions and 59 deletions

9
.gitignore vendored Normal file
View File

@ -0,0 +1,9 @@
venv/*
testdata/*
.vscode/*
.mypy_cache/*
youandme.egg-info/*
__pycache__/*
src/__pycache__/*
src/youandme.egg-info/*
src/youandme/__pycache__/*

View File

@ -1,4 +1,10 @@
import sys
import socket
from time import time, sleep
from threading import Thread
from getch import getch
from stem.control import Controller
try:
from youandme.tor import launch_tor
@ -6,16 +12,77 @@ except ModuleNotFoundError:
pass
from youandme.server import server
from youandme.client import client
def interactive_connector():
class _Address:
address = ""
def connector(host, send_data, recv_data, address="", control_port=1337, socks_port=1338):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
result = sock.connect_ex(('127.0.0.1', socks_port))
if result != 0:
launch_tor(control_port=control_port, socks_port=socks_port)
print(host)
if host:
with Controller.from_port(port=control_port) as controller:
controller.authenticate()
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
ip = '127.0.0.1'
s.bind((ip, 0))
s.listen(1)
port = s.getsockname()[1]
serv = controller.create_ephemeral_hidden_service(
{1337: '127.0.0.1:' + str(port)},
key_content='ED25519-V3',
await_publication=True,
)
_Address.address = serv.service_id
conn, addr = s.accept()
server(1, controller, conn, send_data, recv_data)
else:
print('adderr', address)
if not address.endswith('.onion'):
address += '.onion'
client(1, address, socks_port, send_data, recv_data)
def chat(mode, send_data, recv_data):
if mode == 'host':
while _Address.address == "":
sleep(0.01)
print(_Address.address)
def display_new():
while True:
try:
char = chr(recv_data.pop(0))
print('')
print(char, end='')
except IndexError:
pass
sleep(0.1)
Thread(target=display_new, daemon=True).start()
def make_message():
while True:
new = input().encode('utf-8')
for b in new:
send_data.append(b)
Thread(target=make_message, daemon=True).start()
while True:
sleep(1)
print("Starting Tor...")
launch_tor()
print("Tor started.")
server()
if __name__ == "__main__":
if len(sys.argv) == 2:
if sys.argv[1] == 'interactive':
interactive_connector()
if len(sys.argv) >= 2:
if sys.argv[1] == 'chat':
send_data = bytearray()
recv_data = bytearray()
if sys.argv[2] == 'host':
Thread(target=connector, args=[True, send_data, recv_data], kwargs={'socks_port': int(input("socks")), 'control_port': int(input('control port'))}, daemon=True).start()
elif sys.argv[2].startswith('conn'):
Thread(target=connector, args=[False, send_data, recv_data], kwargs={'address': sys.argv[3], 'socks_port': int(input("socks")), 'control_port': int(input('control port'))}, daemon=True).start()
else:
print('Must specify host or conn')
sys.exit(1)
chat(sys.argv[2], send_data, recv_data)

View File

@ -1,17 +1,11 @@
import sys
import stem
OWN_TOR = False
try:
from .starttor import launch_tor
OWN_TOR = True
except ModuleNotFoundError:
pass
from .server import server
def interactive_connector():
server()
if __name__ == "__main__":
if len(sys.argv) == 2:
if sys.argv[1] == 'interactive':
interactive_connector()

40
src/youandme/client.py Normal file
View File

@ -0,0 +1,40 @@
from threading import Thread
from time import sleep
import socks
from .commands import garbage_character
def client(delay: int, hs_id, socks_port, send_data: bytearray, recv_data: bytearray):
s = socks.socksocket() # Same API as socket.socket in the standard lib
s.set_proxy(socks.SOCKS5, "127.0.0.1", socks_port, rdns=True)
def send_loop():
while True:
to_send = None
if send_data:
char = send_data.pop(0)
to_send = char
else:
to_send = garbage_character
try:
s.send(chr(to_send).encode('utf-8'))
except TypeError:
s.send(to_send)
except BrokenPipeError:
pass
sleep(delay)
# Can be treated identical to a regular socket object
s.connect((hs_id, 1337))
Thread(target=send_loop, daemon=True).start()
while True:
data = s.recv(1)
if data != garbage_character:
try:
recv_data.append(data)
except TypeError:
if data:
recv_data.append(ord(data))

1
src/youandme/commands.py Normal file
View File

@ -0,0 +1 @@
garbage_character = b'\x00'

View File

@ -1,41 +1,34 @@
import socket
import time
from.commands import garbage_character
from stem.control import Controller
from threading import Thread
def server():
send_data = bytearray()
def send_loop(conn):
def server(delay: int, controller, conn, send_data: bytearray, recv_data: bytearray):
def send_loop():
while True:
time.sleep(0.1)
if not send_data:
conn.sendall(bytes([55]))
else:
conn.sendall(send_data.pop(0))
with Controller.from_port(port=1338) as controller:
controller.authenticate()
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
ip = '127.0.0.1'
s.bind((ip, 0))
s.listen(1)
port = s.getsockname()[1]
serv = controller.create_ephemeral_hidden_service({
1337: f'{ip}:{port}'},
key_content = 'ED25519-V3',
await_publication = True,
)
print('on', serv.service_id, 'to', ip, port)
conn, addr = s.accept()
with conn:
Thread(target=send_loop, args=[conn], daemon=True).start()
print('Connected by', addr)
while True:
data = conn.recv(1)
if not data: break
data = data.strip()
if data != bytes([55]):
print(data)
#conn.sendall(data)
time.sleep(delay)
try:
if not send_data:
conn.sendall(garbage_character)
else:
char = send_data.pop(0)
try:
conn.sendall(ord(char))
except TypeError:
try:
conn.sendall(char)
except TypeError:
conn.sendall(chr(char).encode('utf-8'))
except OSError:
pass
with conn:
Thread(target=send_loop, daemon=True).start()
while True:
data = conn.recv(1)
if not data: break
if data != garbage_character and data:
for i in data:
recv_data.append(i)

View File

@ -1,7 +1,7 @@
import stem.process
def launch_tor(control_port="1338", socks_port="1339"):
def launch_tor(control_port="1336", socks_port="1337"):
control_port = str(control_port)
socks_port = str(socks_port)
stem.process.launch_tor_with_config(

View File

@ -1,7 +0,0 @@
import unittest
class TestBasic(unittest.TestCase):
def test_basic(self):
self.assertTrue(True)
unittest.main()

42
tests/test_client.py Normal file
View File

@ -0,0 +1,42 @@
import unittest
import socket
from threading import Thread
import time
import stem
import stem.process
from stem.control import Controller
from youandme import client
control_port = str(1353)
socks_port = str(1354)
stem.process.launch_tor_with_config(
config = {
'ControlPort': control_port,
'SocksPort': socks_port,
'Log': [
'NOTICE stdout'
],
}, take_ownership=True)
def send_test_data(ip, port):
time.sleep(2)
s = socket.socket()
s.connect(('127.0.0.1', port))
while True:
s.send(b"test")
for c in b"test2":
try:
s.send(chr(c).encode('utf8'))
except TypeError:
print(c)
s.close()
class TestClient(unittest.TestCase):
def test_client(self):
send_data = bytearray()
recv_data = bytearray()
#client(1, )
unittest.main()

79
tests/test_server.py Normal file
View File

@ -0,0 +1,79 @@
import unittest
import socket
from threading import Thread
import time
import stem
import stem.process
from stem.control import Controller
from youandme import server
control_port = str(1353)
socks_port = str(1354)
stem.process.launch_tor_with_config(
config = {
'ControlPort': control_port,
'SocksPort': socks_port,
'Log': [
'NOTICE stdout'
],
}, take_ownership=True)
def send_test_data(ip, port):
time.sleep(2)
s = socket.socket()
s.connect(('127.0.0.1', port))
while True:
s.send(b"test")
for c in b"test2":
try:
s.send(chr(c).encode('utf8'))
except TypeError:
print(c)
s.close()
class TestServer(unittest.TestCase):
def test_server(self):
send_data = bytearray()
recv_data = bytearray()
with Controller.from_port(port=int(control_port)) as controller:
controller.authenticate()
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
ip = '127.0.0.1'
s.bind((ip, 0))
s.listen(1)
port = s.getsockname()[1]
print(port)
serv = controller.create_ephemeral_hidden_service(
{1337: f'{ip}:{port}'},
key_content='ED25519-V3',
await_publication=True,
)
Thread(target=send_test_data, args=[ip, port], daemon=True).start()
conn, addr = s.accept()
Thread(target=server, args=[0.1, controller, conn, send_data, recv_data], daemon=True).start()
time.sleep(1)
max_iters = 10000000
c = 0
tested = False
filler_rec = False
while True:
c += 1
if c >= max_iters:
break
try:
char = chr(recv_data.pop(0)).encode('utf8')
if char != b'\n':
tested = True
self.assertIn(char, b"testtest2")
except IndexError:
pass
else:
pass
if send_data:
print(send_data)
if not tested:
raise ValueError('not tested')
unittest.main()