mirror of
https://github.com/house-of-vanity/OutFleet.git
synced 2025-07-06 17:14:07 +00:00
new links
This commit is contained in:
86
main.py
86
main.py
@ -7,11 +7,13 @@ import random
|
|||||||
import string
|
import string
|
||||||
import argparse
|
import argparse
|
||||||
import uuid
|
import uuid
|
||||||
|
import bcrypt
|
||||||
|
|
||||||
|
|
||||||
import k8s
|
import k8s
|
||||||
from flask import Flask, render_template, request, url_for, redirect
|
from flask import Flask, render_template, request, url_for, redirect
|
||||||
from flask_cors import CORS
|
from flask_cors import CORS
|
||||||
|
from werkzeug.routing import BaseConverter
|
||||||
from lib import Server, write_config, get_config, args, lock
|
from lib import Server, write_config, get_config, args, lock
|
||||||
|
|
||||||
|
|
||||||
@ -23,6 +25,15 @@ logging.basicConfig(
|
|||||||
datefmt="%d-%m-%Y %H:%M:%S",
|
datefmt="%d-%m-%Y %H:%M:%S",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
app = Flask(__name__)
|
||||||
|
|
||||||
|
class RegexConverter(BaseConverter):
|
||||||
|
def __init__(self, url_map, *items):
|
||||||
|
super(RegexConverter, self).__init__(url_map)
|
||||||
|
self.regex = items[0]
|
||||||
|
|
||||||
|
app.url_map.converters['regex'] = RegexConverter
|
||||||
|
|
||||||
log = logging.getLogger("OutFleet")
|
log = logging.getLogger("OutFleet")
|
||||||
file_handler = logging.FileHandler("sync.log")
|
file_handler = logging.FileHandler("sync.log")
|
||||||
formatter = logging.Formatter(
|
formatter = logging.Formatter(
|
||||||
@ -37,7 +48,9 @@ SERVERS = list()
|
|||||||
BROKEN_SERVERS = list()
|
BROKEN_SERVERS = list()
|
||||||
CLIENTS = dict()
|
CLIENTS = dict()
|
||||||
VERSION = '6'
|
VERSION = '6'
|
||||||
|
SECRET_LINK_LENGTH = 8
|
||||||
HOSTNAME = ""
|
HOSTNAME = ""
|
||||||
|
WRONG_DOOR = "Hey buddy, i think you got the wrong door the leather-club is two blocks down"
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
CORS(app)
|
CORS(app)
|
||||||
|
|
||||||
@ -52,9 +65,7 @@ def random_string(length=64):
|
|||||||
return "".join(random.choice(letters) for i in range(length))
|
return "".join(random.choice(letters) for i in range(length))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def update_state(timer=40):
|
def update_state(timer=40):
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
with lock:
|
with lock:
|
||||||
global SERVERS
|
global SERVERS
|
||||||
@ -181,6 +192,7 @@ def add_server():
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@app.route("/del_server", methods=["POST"])
|
@app.route("/del_server", methods=["POST"])
|
||||||
def del_server():
|
def del_server():
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
@ -302,8 +314,64 @@ def del_client():
|
|||||||
return redirect(url_for("clients", nt="User has been deleted"))
|
return redirect(url_for("clients", nt="User has been deleted"))
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/dynamic/<hash_secret>", methods=["GET"], strict_slashes=False)
|
||||||
|
def dynamic(hash_secret):
|
||||||
|
try:
|
||||||
|
short_hash_server = hash_secret[0:SECRET_LINK_LENGTH]
|
||||||
|
short_hash_client = hash_secret[SECRET_LINK_LENGTH:SECRET_LINK_LENGTH * 2 ]
|
||||||
|
client_provided_secret = hash_secret[SECRET_LINK_LENGTH * 2:]
|
||||||
|
hash_server = None
|
||||||
|
hash_client = None
|
||||||
|
server = None
|
||||||
|
client = None
|
||||||
|
log.info(f"short_hash_server {short_hash_server} short_hash_client {short_hash_client} client_provided_secret {client_provided_secret}")
|
||||||
|
for _server in SERVERS:
|
||||||
|
if _server.data["local_server_id"][:SECRET_LINK_LENGTH] == short_hash_server:
|
||||||
|
hash_server = _server.data["local_server_id"]
|
||||||
|
server = _server
|
||||||
|
|
||||||
|
for client_id, values in CLIENTS.items():
|
||||||
|
if client_id[:SECRET_LINK_LENGTH] == short_hash_client:
|
||||||
|
hash_client = client_id
|
||||||
|
client = CLIENTS[client_id]
|
||||||
|
|
||||||
|
if server and client:
|
||||||
|
client_shadowsocks_key = next(
|
||||||
|
(item for item in server.data["keys"] if item.key_id == client["name"]), None
|
||||||
|
)
|
||||||
|
|
||||||
|
salt = bcrypt.gensalt()
|
||||||
|
secret_string = hash_server + hash_client
|
||||||
|
hash_password = bcrypt.hashpw(
|
||||||
|
password=secret_string.encode('utf-8'),
|
||||||
|
salt=salt
|
||||||
|
)
|
||||||
|
hash_password =
|
||||||
|
log.info(f"")
|
||||||
|
log.info(f"got srv {short_hash_server}, clt {short_hash_client}, correct secret {hash_password}")
|
||||||
|
check_secret_hash = bcrypt.checkpw(
|
||||||
|
password=secret_string.encode('utf-8'),
|
||||||
|
hashed_password=client_provided_secret.encode('utf-8')
|
||||||
|
)
|
||||||
|
if check_secret_hash:
|
||||||
|
return {
|
||||||
|
"server": server.data["hostname_for_access_keys"],
|
||||||
|
"server_port": client_shadowsocks_key.port,
|
||||||
|
"password": client_shadowsocks_key.password,
|
||||||
|
"method": client_shadowsocks_key.method,
|
||||||
|
"info": "Managed by OutFleet [github.com/house-of-vanity/OutFleet/]",
|
||||||
|
}
|
||||||
|
else:
|
||||||
|
return WRONG_DOOR
|
||||||
|
else:
|
||||||
|
return WRONG_DOOR
|
||||||
|
except Exception as e:
|
||||||
|
log.info(f"EXP: {e}")
|
||||||
|
return WRONG_DOOR
|
||||||
|
|
||||||
|
|
||||||
@app.route("/dynamic/<server_name>/<client_id>", methods=["GET"], strict_slashes=False)
|
@app.route("/dynamic/<server_name>/<client_id>", methods=["GET"], strict_slashes=False)
|
||||||
def dynamic(server_name, client_id):
|
def dynamic_depticated(server_name, client_id):
|
||||||
try:
|
try:
|
||||||
client = next(
|
client = next(
|
||||||
(keys for client, keys in CLIENTS.items() if client == client_id), None
|
(keys for client, keys in CLIENTS.items() if client == client_id), None
|
||||||
@ -332,18 +400,17 @@ def dynamic(server_name, client_id):
|
|||||||
client["name"],
|
client["name"],
|
||||||
server.data["name"],
|
server.data["name"],
|
||||||
)
|
)
|
||||||
return "Hey buddy, i think you got the wrong door the leather-club is two blocks down"
|
return WRONG_DOOR
|
||||||
except:
|
except:
|
||||||
log.warning("Hack attempt! Client or server doesn't exist. SCAM")
|
log.warning("Hack attempt! Client or server doesn't exist. SCAM")
|
||||||
return "Hey buddy, i think you got the wrong door the leather-club is two blocks down"
|
return WRONG_DOOR
|
||||||
|
|
||||||
|
|
||||||
@app.route("/dynamic/", methods=["GET"], strict_slashes=False)
|
|
||||||
|
@app.route("/dynamic", methods=["GET"], strict_slashes=False)
|
||||||
def _dynamic():
|
def _dynamic():
|
||||||
log.warning("Hack attempt! Client or server doesn't exist. SCAM")
|
log.warning("Hack attempt! Client or server doesn't exist. SCAM")
|
||||||
return (
|
return WRONG_DOOR
|
||||||
"Hey buddy, i think you got the wrong door the leather-club is two blocks down"
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@app.route("/sync", methods=["GET", "POST"])
|
@app.route("/sync", methods=["GET", "POST"])
|
||||||
@ -393,6 +460,7 @@ def sync():
|
|||||||
return redirect(url_for("sync"))
|
return redirect(url_for("sync"))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
update_state_thread = threading.Thread(target=update_state)
|
update_state_thread = threading.Thread(target=update_state)
|
||||||
update_state_thread.start()
|
update_state_thread.start()
|
||||||
|
@ -2,4 +2,5 @@ outline-vpn-api
|
|||||||
kubernetes
|
kubernetes
|
||||||
PyYAML>=6.0.1
|
PyYAML>=6.0.1
|
||||||
Flask>=2.3.3
|
Flask>=2.3.3
|
||||||
flask-cors
|
flask-cors
|
||||||
|
bcrypt
|
Reference in New Issue
Block a user