Merge branch 'main' into dev
This commit is contained in:
18
README.md
18
README.md
@@ -6,21 +6,3 @@ A relay server is used to help with data transfer.
|
|||||||
**transphase** - the relay server \
|
**transphase** - the relay server \
|
||||||
**transmat** - tool to copy files/directories \
|
**transmat** - tool to copy files/directories \
|
||||||
**transplace** - HTTP proxy/exit point
|
**transplace** - HTTP proxy/exit point
|
||||||
|
|
||||||
### How to copy files using ```transmat```
|
|
||||||
Transphase relay server should be running and accessible by the parties.
|
|
||||||
On the sending party:
|
|
||||||
```
|
|
||||||
transmat --send <FILENAME>
|
|
||||||
```
|
|
||||||
This will prepare the sender and output the command to run on the receiving party, eg:
|
|
||||||
```
|
|
||||||
transmat --receive --password Space-Time-Continuum
|
|
||||||
```
|
|
||||||
|
|
||||||
The sending party will wait for the receiving party to connect to the relay server, and then it will start the transfer. \
|
|
||||||
With the exception of some service messages, all the data is encrypted. \
|
|
||||||
Encryption and decryption is done only client-side, and the relay server has no useful knowledge of the data it relays. \
|
|
||||||
Fernet module (AES128-CBC + HMAC-SHA256) is used to encrypt and authenticate the data.
|
|
||||||
|
|
||||||
See also ```transmat --help```
|
|
||||||
@@ -1,6 +1,2 @@
|
|||||||
asyncio==3.4.3
|
|
||||||
cffi==1.15.1
|
|
||||||
cryptography==40.0.2
|
cryptography==40.0.2
|
||||||
pycparser==2.21
|
quart
|
||||||
pyjson==1.3.0
|
|
||||||
websockets==11.0.2
|
|
||||||
59
transphase/transphase.py
Executable file → Normal file
59
transphase/transphase.py
Executable file → Normal file
@@ -1,58 +1,33 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
import asyncio
|
|
||||||
import websockets
|
|
||||||
import logging
|
|
||||||
import json
|
import json
|
||||||
|
import asyncio
|
||||||
|
from quart import Quart, websocket
|
||||||
logging.basicConfig(
|
|
||||||
format="%(asctime)s %(message)s",
|
|
||||||
level=logging.INFO,
|
|
||||||
)
|
|
||||||
|
|
||||||
peer_list = {}
|
peer_list = {}
|
||||||
|
|
||||||
class LoggerAdapter(logging.LoggerAdapter):
|
app = Quart(__name__)
|
||||||
"""Add connection ID and client IP address to websockets logs."""
|
|
||||||
def process(self, msg, kwargs):
|
|
||||||
try:
|
|
||||||
websocket = kwargs["extra"]["websocket"]
|
|
||||||
except KeyError:
|
|
||||||
return msg, kwargs
|
|
||||||
rip = websocket.remote_address[0]
|
|
||||||
try:
|
|
||||||
xff = websocket.request_headers.get("X-Forwarded-For")
|
|
||||||
except:
|
|
||||||
xff = "None"
|
|
||||||
return f"{websocket.id} {rip} {xff}", kwargs
|
|
||||||
|
|
||||||
async def handler(websocket):
|
@app.route("/")
|
||||||
|
async def retmain():
|
||||||
|
return f"Ready to relay\n"
|
||||||
|
|
||||||
|
@app.websocket("/ws")
|
||||||
|
async def handle_websockets():
|
||||||
peer_group_id = None
|
peer_group_id = None
|
||||||
|
while True:
|
||||||
try:
|
try:
|
||||||
while not websocket.closed:
|
message = await websocket.receive()
|
||||||
message = await websocket.recv()
|
|
||||||
msg = json.loads(message)
|
msg = json.loads(message)
|
||||||
if "peer_group_id" in msg:
|
if "peer_group_id" in msg:
|
||||||
peer_group_id = msg["peer_group_id"]
|
peer_group_id = msg["peer_group_id"]
|
||||||
if peer_group_id not in peer_list:
|
if peer_group_id not in peer_list:
|
||||||
peer_list[peer_group_id] = set() # Create new set for all peers in peer_group_id
|
peer_list[peer_group_id] = set()
|
||||||
peer_list[peer_group_id].add(websocket) # Add peer's socket to peer_group
|
peer_list[peer_group_id].add(websocket._get_current_object())
|
||||||
for peer in peer_list[peer_group_id]:
|
for peer in peer_list[peer_group_id]:
|
||||||
if peer != websocket:
|
if peer != websocket._get_current_object():
|
||||||
await peer.send(message)
|
await peer.send(message)
|
||||||
except websockets.exceptions.ConnectionClosed as e:
|
except asyncio.exceptions.CancelledError:
|
||||||
pass
|
peer_list[peer_group_id].remove(websocket._get_current_object())
|
||||||
finally:
|
|
||||||
peer_list[peer_group_id].remove(websocket)
|
|
||||||
if len(peer_list[peer_group_id]) < 1:
|
if len(peer_list[peer_group_id]) < 1:
|
||||||
peer_list.pop(peer_group_id)
|
peer_list.pop(peer_group_id)
|
||||||
|
|
||||||
async def main():
|
app.run()
|
||||||
async with websockets.serve(
|
|
||||||
handler, "", 8001, ping_timeout=30,
|
|
||||||
logger=LoggerAdapter(logging.getLogger("websockets.server"), None),
|
|
||||||
):
|
|
||||||
await asyncio.Future() # run forever
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
asyncio.run(main())
|
|
||||||
Reference in New Issue
Block a user