added connection loss detection, strict printable character filter support
This commit is contained in:
parent
e47173b586
commit
0173f136fb
11
CHANGELOG.md
11
CHANGELOG.md
@ -2,6 +2,17 @@
|
|||||||
|
|
||||||
This project uses Semantic Versioning
|
This project uses Semantic Versioning
|
||||||
|
|
||||||
|
|
||||||
|
## 1.1.1
|
||||||
|
|
||||||
|
Fixed setup.py project URL
|
||||||
|
|
||||||
|
|
||||||
|
## 1.1.0
|
||||||
|
|
||||||
|
Added detection of connection loss
|
||||||
|
Added --alphanum-only argument
|
||||||
|
|
||||||
## 1.0.0
|
## 1.0.0
|
||||||
|
|
||||||
Made yam a proper script (install and you can run from path with $ yam.py <args>)
|
Made yam a proper script (install and you can run from path with $ yam.py <args>)
|
||||||
|
4
setup.py
4
setup.py
@ -7,7 +7,7 @@ with open(path.join(this_directory, 'README.md'), encoding='utf-8') as f:
|
|||||||
packages = find_packages(exclude=['contrib', 'docs', 'tests'])
|
packages = find_packages(exclude=['contrib', 'docs', 'tests'])
|
||||||
|
|
||||||
setup(name='youandme',
|
setup(name='youandme',
|
||||||
version='1.0.0',
|
version='1.1.1',
|
||||||
description='Simple private data sharing via bytearrays, Tor tunneling and metadata paranoia',
|
description='Simple private data sharing via bytearrays, Tor tunneling and metadata paranoia',
|
||||||
long_description=long_description,
|
long_description=long_description,
|
||||||
long_description_content_type='text/markdown',
|
long_description_content_type='text/markdown',
|
||||||
@ -15,7 +15,7 @@ setup(name='youandme',
|
|||||||
packages=packages,
|
packages=packages,
|
||||||
scripts=['src/yam/yam.py'],
|
scripts=['src/yam/yam.py'],
|
||||||
author_email='beardog@mailbox.org',
|
author_email='beardog@mailbox.org',
|
||||||
url='https://chaoswebs.net',
|
url='http://github.com/beardog108/youandme',
|
||||||
install_requires=[
|
install_requires=[
|
||||||
'stem',
|
'stem',
|
||||||
'PySocks'
|
'PySocks'
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
import sys
|
import sys
|
||||||
import socket
|
import socket
|
||||||
from time import time, sleep
|
from time import sleep
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
import tempfile
|
import tempfile
|
||||||
import argparse
|
import argparse
|
||||||
|
from string import printable
|
||||||
|
|
||||||
|
import socks
|
||||||
from stem.control import Controller
|
from stem.control import Controller
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -16,9 +18,15 @@ except ModuleNotFoundError:
|
|||||||
from youandme.server import server
|
from youandme.server import server
|
||||||
from youandme.client import client
|
from youandme.client import client
|
||||||
|
|
||||||
|
|
||||||
|
class Connection:
|
||||||
|
connected = True
|
||||||
|
|
||||||
class _Address:
|
class _Address:
|
||||||
address = ""
|
address = ""
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def _get_open_port():
|
def _get_open_port():
|
||||||
# taken from (but modified) https://stackoverflow.com/a/2838309 by https://stackoverflow.com/users/133374/albert ccy-by-sa-3 https://creativecommons.org/licenses/by-sa/3.0/
|
# taken from (but modified) https://stackoverflow.com/a/2838309 by https://stackoverflow.com/users/133374/albert ccy-by-sa-3 https://creativecommons.org/licenses/by-sa/3.0/
|
||||||
# changes from source: import moved to top of file, bind specifically to localhost
|
# changes from source: import moved to top of file, bind specifically to localhost
|
||||||
@ -54,29 +62,38 @@ def connector(host, send_data, recv_data, address="", control_port=1337, socks_p
|
|||||||
)
|
)
|
||||||
_Address.address = serv.service_id
|
_Address.address = serv.service_id
|
||||||
conn, addr = s.accept()
|
conn, addr = s.accept()
|
||||||
server(0.01, controller, conn, send_data, recv_data)
|
server(0.01, controller, conn, send_data, recv_data, Connection)
|
||||||
else:
|
else:
|
||||||
if not address.endswith('.onion'):
|
if not address.endswith('.onion'):
|
||||||
address += '.onion'
|
address += '.onion'
|
||||||
client(0.01, address, socks_port, send_data, recv_data)
|
try:
|
||||||
|
client(0.01, address, socks_port, send_data, recv_data, Connection)
|
||||||
|
except socks.GeneralProxyError:
|
||||||
|
Connection.connected = False
|
||||||
|
|
||||||
|
def chat(mode, send_data, recv_data, alpha):
|
||||||
def chat(mode, send_data, recv_data):
|
print("A notice will be shown when connection is established, but messages may be typed now.")
|
||||||
display_buffer = []
|
display_buffer = []
|
||||||
|
|
||||||
if mode == 'host':
|
if mode == 'host':
|
||||||
|
print('Creating tunnel...')
|
||||||
while _Address.address == "":
|
while _Address.address == "":
|
||||||
sleep(0.01)
|
sleep(0.01)
|
||||||
|
print('Tunnel address:')
|
||||||
print(_Address.address)
|
print(_Address.address)
|
||||||
|
|
||||||
def display_new():
|
def display_new():
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
char = chr(recv_data.pop(0))
|
char = chr(recv_data.pop(0))
|
||||||
display_buffer.append(char)
|
display_buffer.append(char)
|
||||||
if char == "\n" or char == "\r\n" or len(display_buffer) > 100:
|
if char == "\n" or char == "\r\n" or len(display_buffer) > 100:
|
||||||
#print("\033[1;33m", char, "\033[0m", end="\n")
|
|
||||||
while len(display_buffer) != 0:
|
while len(display_buffer) != 0:
|
||||||
#print("\033[1;33m", display_buffer.pop(0), "\033[0m", end='')
|
char = display_buffer.pop(0)
|
||||||
print("\033[1;33m" + display_buffer.pop(0) + "\033[0m", end="")
|
if alpha and char not in printable and \
|
||||||
|
char not in ('\n', '\r', ' ', '\t'):
|
||||||
|
continue
|
||||||
|
print("\033[1;33m" + char + "\033[0m", end="")
|
||||||
|
|
||||||
except IndexError:
|
except IndexError:
|
||||||
pass
|
pass
|
||||||
@ -91,8 +108,8 @@ def chat(mode, send_data, recv_data):
|
|||||||
Thread(target=make_message, daemon=True).start()
|
Thread(target=make_message, daemon=True).start()
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
if send_data is None:
|
if not Connection.connected:
|
||||||
print("Well crap, we lost connection.")
|
print("Cease dancing ☹️")
|
||||||
break
|
break
|
||||||
sleep(1)
|
sleep(1)
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
@ -100,10 +117,11 @@ def chat(mode, send_data, recv_data):
|
|||||||
PORT_MESSAGE = "Specify any free ports above 1023"
|
PORT_MESSAGE = "Specify any free ports above 1023"
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
parser = argparse.ArgumentParser(description='End-to-end encrpyted instant messaging with metadata privacy and perfect forward secrecy')
|
parser = argparse.ArgumentParser(description='End-to-end encrypted instant messaging with metadata privacy and perfect forward secrecy')
|
||||||
parser.add_argument('connection', choices=['host', 'conn'])
|
parser.add_argument('connection', choices=['host', 'conn'])
|
||||||
parser.add_argument('--socks-port', help='Socks proxy port (will use random if not given)', default=0, type=int)
|
parser.add_argument('--socks-port', help='Socks proxy port (will use random if not given)', default=0, type=int)
|
||||||
parser.add_argument('--control-port', help='Tor control port (will use random if not given)', default=0, type=int)
|
parser.add_argument('--control-port', help='Tor control port (will use random if not given)', default=0, type=int)
|
||||||
|
parser.add_argument('--alphanum-only', help='Only allow english alpha-numeric characters and spaces/tabs/new lines', default=False, type=bool)
|
||||||
parser.add_argument('--address', help='Address to connect to. No port.', default='')
|
parser.add_argument('--address', help='Address to connect to. No port.', default='')
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
@ -120,9 +138,9 @@ if __name__ == "__main__":
|
|||||||
kwargs={'address': args.address,
|
kwargs={'address': args.address,
|
||||||
'socks_port': args.socks_port,
|
'socks_port': args.socks_port,
|
||||||
'control_port': args.control_port}, daemon=True).start()
|
'control_port': args.control_port}, daemon=True).start()
|
||||||
chat('conn', send_data, recv_data)
|
chat('conn', send_data, recv_data, args.alphanum_only)
|
||||||
else:
|
else:
|
||||||
Thread(target=connector, args=[True, send_data, recv_data],
|
Thread(target=connector, args=[True, send_data, recv_data],
|
||||||
kwargs={'socks_port': args.socks_port,
|
kwargs={'socks_port': args.socks_port,
|
||||||
'control_port': args.control_port}, daemon=True).start()
|
'control_port': args.control_port}, daemon=True).start()
|
||||||
chat('host', send_data, recv_data)
|
chat('host', send_data, recv_data, args.alphanum_only)
|
@ -4,14 +4,17 @@ from time import sleep
|
|||||||
import socks
|
import socks
|
||||||
|
|
||||||
from .commands import garbage_character
|
from .commands import garbage_character
|
||||||
|
from .commands import WELCOME_MESSAGE
|
||||||
|
|
||||||
|
|
||||||
def client(delay: int, hs_id, socks_port, send_data: bytearray, recv_data: bytearray):
|
def client(delay: int, hs_id, socks_port, send_data: bytearray, recv_data: bytearray, connection: "Connection"):
|
||||||
s = socks.socksocket() # Same API as socket.socket in the standard lib
|
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)
|
s.set_proxy(socks.SOCKS5, "127.0.0.1", socks_port, rdns=True)
|
||||||
|
|
||||||
def send_loop():
|
def send_loop():
|
||||||
|
for i in WELCOME_MESSAGE:
|
||||||
|
send_data.append(ord(i))
|
||||||
while True:
|
while True:
|
||||||
to_send = None
|
to_send = None
|
||||||
if send_data:
|
if send_data:
|
||||||
@ -27,9 +30,9 @@ def client(delay: int, hs_id, socks_port, send_data: bytearray, recv_data: bytea
|
|||||||
s.send(to_send)
|
s.send(to_send)
|
||||||
except BrokenPipeError:
|
except BrokenPipeError:
|
||||||
# lost connection
|
# lost connection
|
||||||
pass
|
connection.connected = False
|
||||||
except BrokenPipeError:
|
except BrokenPipeError:
|
||||||
pass
|
connection.connected = False
|
||||||
sleep(delay)
|
sleep(delay)
|
||||||
|
|
||||||
# Can be treated identical to a regular socket object
|
# Can be treated identical to a regular socket object
|
||||||
|
@ -1 +1,2 @@
|
|||||||
garbage_character = b'\x00'
|
garbage_character = b'\x00'
|
||||||
|
WELCOME_MESSAGE = "Connection established. Dance like no one is watching :)\n"
|
@ -1,11 +1,12 @@
|
|||||||
import socket
|
import socket
|
||||||
import time
|
import time
|
||||||
from.commands import garbage_character
|
from.commands import garbage_character
|
||||||
|
from.commands import WELCOME_MESSAGE
|
||||||
|
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
|
|
||||||
|
|
||||||
def server(delay: int, controller, conn, send_data: bytearray, recv_data: bytearray):
|
def server(delay: int, controller, conn, send_data: bytearray, recv_data: bytearray, connection: "Connection"):
|
||||||
def send_loop():
|
def send_loop():
|
||||||
while True:
|
while True:
|
||||||
time.sleep(delay)
|
time.sleep(delay)
|
||||||
@ -22,15 +23,15 @@ def server(delay: int, controller, conn, send_data: bytearray, recv_data: bytear
|
|||||||
except TypeError:
|
except TypeError:
|
||||||
conn.sendall(chr(char).encode('utf-8'))
|
conn.sendall(chr(char).encode('utf-8'))
|
||||||
except OSError:
|
except OSError:
|
||||||
pass
|
connection.connected = False
|
||||||
first_rec = True
|
first_rec = True
|
||||||
WELCOME_MESSAGE = "Connection established\n"
|
|
||||||
with conn:
|
with conn:
|
||||||
Thread(target=send_loop, daemon=True).start()
|
Thread(target=send_loop, daemon=True).start()
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
data = conn.recv(1)
|
data = conn.recv(1)
|
||||||
except ConnectionResetError:
|
except ConnectionResetError:
|
||||||
|
connection.connected = False
|
||||||
break
|
break
|
||||||
if not data: break
|
if not data: break
|
||||||
if first_rec:
|
if first_rec:
|
||||||
|
Loading…
Reference in New Issue
Block a user