-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
0a67a30
commit 3c1d1fa
Showing
14 changed files
with
458 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
Copyright 2017 Hyperion Gray LLC | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
templates/ | ||
*.html | ||
static/ | ||
*.ico |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,60 @@ | ||
# DeadDrop | ||
An in-memory messenger that uses Tor Browser for clientless, private messaging | ||
Platform | ||
======== | ||
|
||
To be a dropchat server host requires a Linux machine (any Linux should do), if this gets more popular we will create one for Windows. | ||
|
||
To be a dropchat client requires a Tor Browser on any OS. | ||
|
||
|
||
Install | ||
======= | ||
|
||
Install Tor | ||
|
||
Activate your favorite virtualenv e.g.. | ||
|
||
`$ sudo apt-get install python-virtualenv` | ||
|
||
`$ virtualenv dropenv` | ||
|
||
`$ source dropenv/bin/activate` | ||
|
||
`$ pip install git+https://gitlab.com/hyperion-gray/dropchat.git` | ||
|
||
That's it! | ||
|
||
How it works | ||
============ | ||
|
||
Dropchat is a disposable mini-chat server that can be used to chat safely and anonymously through Tor. One | ||
person is the host of the chat server (don't worry being a host only requires one command - no messing with | ||
complex config files) and the others are the clients using only a Tor Browser. The host starts the server | ||
and shares a URL with the clients. They can then chat with each other safely and anonymously. Once you're | ||
done sharing the info you want, simply kill the server. No information is stored on disk. | ||
|
||
Usage | ||
===== | ||
|
||
Start Tor or Tor Browser, make sure your Control Port is open and listening on the default port. | ||
|
||
`$ dropchat` | ||
|
||
Share the drop URL with your friends to open in Tor Browser. Chat with them safely and securely! | ||
|
||
Features | ||
======== | ||
|
||
- As chat happens inside the Tor network via ephemeral hidden services, everything is encrypted and attribution of chatters is virtually impossible | ||
- No JS required, use safely with NoScript | ||
- *Nothing* touches disk, everything happens in-memory | ||
- No configuration required | ||
- Low barrier to entry, few dependencies | ||
- No need for a client | ||
- Chats are deleted every 3 minutes | ||
- Randomized usernames - this is for your own safety, so as to decrease chances of username reuse | ||
- New chat service created every time the server is started | ||
- No frills, no fancy CSS, code is easy to follow and review to ensure your safety | ||
|
||
--- | ||
|
||
[](https://hyperiongray.com/?pk_campaign=github&pk_kwd=dropchat "Hyperion Gray") |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
#!/bin/bash | ||
# Init | ||
FILE="/tmp/out.$$" | ||
GREP="/bin/grep" | ||
#.... | ||
# Make sure only root can run our script | ||
if [[ $EUID -ne 0 ]]; then | ||
echo "[!] This script must be run as root, and not with sudo. Please su to root and run." 1>&2 | ||
exit 1 | ||
fi | ||
|
||
echo "[*] Clearing ram..." | ||
sync; echo 3 > /proc/sys/vm/drop_caches | ||
echo "[*] Done." |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
flask | ||
stem |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,189 @@ | ||
from flask import Flask | ||
from flask import render_template | ||
from flask import request, session, url_for, redirect, abort, jsonify | ||
import traceback | ||
import sys | ||
import string | ||
from stem.control import Controller | ||
from hashlib import sha224 | ||
import random | ||
import datetime | ||
from stem import SocketError | ||
import textwrap | ||
app = Flask(__name__) | ||
import logging | ||
log = logging.getLogger('werkzeug') | ||
log.setLevel(logging.ERROR) | ||
|
||
|
||
chatters = [] | ||
global chatlines | ||
chatlines = [] | ||
|
||
def id_generator(size=6, | ||
chars=string.ascii_uppercase + string.digits + | ||
string.ascii_lowercase): | ||
|
||
return ''.join(random.choice(chars) for i in range(size)) | ||
|
||
|
||
app.secret_key = id_generator(size=64) | ||
|
||
|
||
def check_older_than(chat_dic, secs_to_live = 180): | ||
now = datetime.datetime.now() | ||
timestamp = chat_dic["timestamp"] | ||
diff = now - timestamp | ||
secs = diff.total_seconds() | ||
|
||
if secs >= secs_to_live: | ||
return True | ||
|
||
return False | ||
|
||
|
||
def get_random_color(): | ||
|
||
r = lambda: random.randint(0,128) | ||
return (r(),r(),r()) | ||
|
||
|
||
def process_chat(chat_dic): | ||
|
||
chats = [] | ||
max_chat_len = 69 | ||
if len(chat_dic["msg"]) > max_chat_len: | ||
|
||
for message in textwrap.wrap(chat_dic["msg"], width = max_chat_len): | ||
partial_chat = {} | ||
partial_chat["msg"] = message.strip() | ||
partial_chat["timestamp"] = datetime.datetime.now() | ||
partial_chat["username"] = session["_id"] | ||
partial_chat["color"] = session["color"] | ||
chats.append(partial_chat) | ||
|
||
else: | ||
chats = [chat_dic] | ||
|
||
return chats | ||
|
||
|
||
# Remove headers that can be used to fingerprint this server | ||
@app.after_request | ||
def remove_headers(response): | ||
response.headers["Server"] = "" | ||
response.headers["Date"] = "" | ||
return response | ||
|
||
|
||
# Empty Index page to avoid Flask fingerprinting | ||
@app.route('/', methods=["GET"]) | ||
def index(): | ||
return ('', 200) | ||
|
||
|
||
@app.route('/<string:url_addition>', methods=["GET"]) | ||
def drop(url_addition): | ||
|
||
if url_addition != app.config["path"]: | ||
return ('', 404) | ||
|
||
if "_id" not in session: | ||
session["_id"] = id_generator() | ||
chatters.append(session["_id"]) | ||
session["color"] = get_random_color() | ||
|
||
if request.method == "GET": | ||
full_path = app.config["hostname"] + "/" + app.config["path"] | ||
return render_template("drop.html", | ||
hostname=app.config["hostname"], | ||
path=app.config["path"]) | ||
|
||
|
||
@app.route('/<string:url_addition>/chats', methods=["GET", "POST"]) | ||
def chat_messages(url_addition): | ||
|
||
global chatlines | ||
more_chats = False | ||
if url_addition != app.config["path"]: | ||
return ('', 404) | ||
|
||
to_delete = [] | ||
c = 0 | ||
if chatlines: | ||
for chatline_dic in chatlines: | ||
if check_older_than(chatline_dic): | ||
to_delete.append(c) | ||
|
||
c += 1 | ||
|
||
for _del in to_delete: | ||
chatlines.pop(_del) | ||
|
||
if request.method == "POST": | ||
|
||
if request.form["dropdata"].strip(): | ||
|
||
chat = {} | ||
chat["msg"] = request.form["dropdata"].strip() | ||
chat["timestamp"] = datetime.datetime.now() | ||
chat["username"] = session["_id"] | ||
chat["color"] = session["color"] | ||
chats = process_chat(chat) | ||
chatlines = chatlines + chats | ||
chatlines = chatlines[-13:] | ||
more_chats = True | ||
|
||
return redirect(app.config["path"], code=302) | ||
|
||
return jsonify(chatlines) | ||
|
||
#return render_template("chats.html", | ||
# chatlines=chatlines, num_people = len(chatters)) | ||
|
||
def main(): | ||
|
||
try: | ||
controller = Controller.from_port() | ||
except SocketError: | ||
sys.stderr.write('[!] Tor proxy or Control Port are not running. Try starting the Tor Browser or Tor daemon and ensure the ControlPort is open.\n') | ||
sys.exit(1) | ||
|
||
|
||
print('[*] Connecting to tor') | ||
with controller: | ||
controller.authenticate() | ||
|
||
# Create ephemeral hidden service where visitors of port 80 get redirected to local | ||
# port 5000 (this is where Flask runs by default). | ||
print('[*] Creating ephemeral hidden service, this may take a minute or two') | ||
result = controller.create_ephemeral_hidden_service({80: 5000}, await_publication = True) | ||
|
||
print("[*] Started a new hidden service with the address of %s.onion" % result.service_id) | ||
###result = controller.create_hidden_service(hidden_service_dir, 80, target_port = 5000) | ||
|
||
# The hostname is only available when we can read the hidden service | ||
# directory. This requires us to be running with the same user as tor. | ||
|
||
if not result: | ||
print("[*] Something went wrong, shutting down") | ||
###controller.remove_hidden_service(hidden_service_dir) | ||
###shutil.rmtree(hidden_service_dir) | ||
|
||
if result.service_id: | ||
app.config["hostname"] = result.service_id | ||
app.config["path"] = id_generator(size = 64) | ||
app.config["full_path"] = app.config["hostname"] + ".onion" + "/" + app.config["path"] | ||
print("[*] Your service is available at: %s , press ctrl+c to quit" % app.config["full_path"]) | ||
else: | ||
print("[*] Unable to determine our ephemeral service's hostname") | ||
|
||
try: | ||
app.run(debug=False, threaded = True) | ||
finally: | ||
|
||
print(" * Shutting down our hidden service") | ||
controller.remove_ephemeral_hidden_service(result.service_id) | ||
|
||
if __name__ == "__main__": | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import os | ||
from setuptools import setup, find_packages | ||
|
||
setup( | ||
name = 'dropchat', | ||
version = '0.3.0', | ||
description = 'DropChat', | ||
long_description = 'Drop Chat - Secure Disposable Chat', | ||
url = '', | ||
license = 'MIT', | ||
author = 'Alejandro Caceres', | ||
author_email = '[email protected]', | ||
packages = [''], | ||
include_package_data = True, | ||
package_data = {'': ['templates/*.html']}, | ||
install_requires = ["flask", "stem"], | ||
classifiers = [ 'Development Status :: 4 - Beta', | ||
'Programming Language :: Python :: 3', | ||
'Programming Language :: Python'], | ||
entry_points = { 'console_scripts': | ||
[ 'dropchat = runserver:main']} | ||
) |
Binary file not shown.
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
<html> | ||
<!--<meta http-equiv="refresh" content="1" >--> | ||
<style> | ||
*{ | ||
padding-top:3px; | ||
font-family: Lucida Sans Typewriter,Lucida Console,monaco,Bitstream Vera Sans Mono,monospace; | ||
font-size:22px; | ||
} | ||
</style> | ||
|
||
<div style="float:right; font-size:10px;">People in chat: {{ num_people }}</div> | ||
<table> | ||
{% for message_dic in chatlines %} | ||
<tr> | ||
<td name="msg" class="msg" style="color:rgb{{ message_dic["color"] }};"><b>{{ message_dic["username"] }}</b>: {{ message_dic["msg"] }}</td> | ||
</tr> | ||
{% endfor %} | ||
</table> | ||
|
||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
<html> | ||
<!--<meta http-equiv="refresh" content="1" >--> | ||
<style> | ||
*{ | ||
padding-top:3px; | ||
font-family: Lucida Sans Typewriter,Lucida Console,monaco,Bitstream Vera Sans Mono,monospace; | ||
font-size:22px; | ||
} | ||
</style> | ||
|
||
<div style="float:right; font-size:10px;">People in chat: {{ num_people }}</div> | ||
<table> | ||
{% for message_dic in chatlines %} | ||
<tr> | ||
<td name="msg" class="msg" style="color:rgb{{ message_dic["color"] }};"><b>{{ message_dic["username"] }}</b>: {{ message_dic["msg"] }}</td> | ||
</tr> | ||
{% endfor %} | ||
</table> | ||
|
||
</html> |
Oops, something went wrong.