-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
🏗️ ✨ Add VMess AEAD CLI module with working server impl
client impl is WIP.
- Loading branch information
Showing
1 changed file
with
168 additions
and
0 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,168 @@ | ||
import asyncio | ||
import contextlib | ||
import logging | ||
import uuid | ||
from typing import Annotated | ||
|
||
from vmess_aead.cli.server import VMessServerProtocol | ||
from vmess_aead.enums import VMessBodySecurity | ||
|
||
try: | ||
import click | ||
import typer | ||
from rich.logging import RichHandler | ||
except ImportError as e: | ||
raise ImportError( | ||
"Please install the extra dependencies for the CLI: pip install vmess-aead[cli]" | ||
) from e | ||
|
||
app = typer.Typer() | ||
|
||
|
||
UUIDType = Annotated[ | ||
uuid.UUID, | ||
typer.Option( | ||
envvar="USER_ID", | ||
help="User ID to identify the client or server.", | ||
), | ||
] | ||
_DEFAULT_USER_ID = uuid.UUID("b831381d-6324-4d53-ad4f-8cda48b30811") | ||
|
||
ListenPortType = Annotated[ | ||
int, | ||
typer.Option( | ||
envvar="LISTEN_PORT", | ||
help="Port to listen or connect.", | ||
click_type=click.IntRange(0x0000, 0xFFFF, min_open=True), | ||
), | ||
] | ||
|
||
ListenAddrType = Annotated[ | ||
str, | ||
typer.Option( | ||
envvar="LISTEN_ADDR", | ||
help="Address to listen.", | ||
), | ||
] | ||
|
||
EnableUDPType = Annotated[ | ||
bool, | ||
typer.Option( | ||
envvar="ENABLE_UDP", | ||
help="Enable UDP relay.", | ||
), | ||
] | ||
|
||
|
||
@app.command() | ||
def server( | ||
user_id: UUIDType = _DEFAULT_USER_ID, | ||
listen_port: ListenPortType = 10086, | ||
listen_addr: ListenAddrType = "0.0.0.0", | ||
enable_udp: EnableUDPType = True, | ||
): | ||
async def server_main(): | ||
loop = asyncio.get_running_loop() | ||
server = await loop.create_server( | ||
lambda: VMessServerProtocol(user_id, enable_udp=enable_udp), | ||
host=listen_addr, | ||
port=listen_port, | ||
) | ||
logging.info("Listening on %s:%d", listen_addr, listen_port) | ||
|
||
async with server: | ||
with contextlib.suppress(KeyboardInterrupt): | ||
await server.serve_forever() | ||
return | ||
|
||
asyncio.run(server_main()) | ||
|
||
|
||
ServerPortType = Annotated[ | ||
int, | ||
typer.Option( | ||
envvar="SERVER_PORT", | ||
help="Port to connect.", | ||
click_type=click.IntRange(0x0000, 0xFFFF, min_open=True), | ||
), | ||
] | ||
|
||
ServerAddrType = Annotated[ | ||
str, | ||
typer.Option( | ||
envvar="SERVER_ADDR", | ||
help="Address to connect.", | ||
), | ||
] | ||
|
||
LocalProtocolType = Annotated[ | ||
str, | ||
typer.Option( | ||
envvar="LOCAL_PROTOCOL", | ||
help="Local proxy protocol to use.", | ||
click_type=click.Choice(["SOCKS5", "HTTP"], case_sensitive=False), | ||
), | ||
] | ||
|
||
ConnectionTimeoutType = Annotated[ | ||
float, | ||
typer.Option( | ||
envvar="CONNECTION_TIMEOUT", | ||
help="Connection timeout to the server, in seconds.", | ||
click_type=click.FloatRange(0, min_open=True), | ||
), | ||
] | ||
|
||
VMessProtocolSecurityType = Annotated[ | ||
str, | ||
typer.Option( | ||
envvar="SECURITY", | ||
help="Security protocol to use.", | ||
click_type=click.Choice( | ||
[security.name for security in VMessBodySecurity], | ||
case_sensitive=False, | ||
), | ||
), | ||
] | ||
|
||
|
||
@app.command() | ||
def client( | ||
server_addr: ServerAddrType, | ||
server_port: ServerPortType, | ||
user_id: UUIDType, | ||
listen_port: ListenPortType = 1080, | ||
listen_addr: ListenAddrType = "127.0.0.1", | ||
enable_udp: EnableUDPType = False, | ||
local_protocol: LocalProtocolType = "SOCKS5", | ||
connection_timeout: ConnectionTimeoutType = 10, | ||
security: VMessProtocolSecurityType = "AES_128_GCM", | ||
): | ||
pass | ||
|
||
|
||
LogLevelType = Annotated[ | ||
str, | ||
typer.Option( | ||
envvar="LOG_LEVEL", | ||
click_type=click.Choice( | ||
[*logging.getLevelNamesMapping().keys()], | ||
case_sensitive=False, | ||
), | ||
help="Logging level, set lower than INFO may reduce performance.", | ||
), | ||
] | ||
|
||
|
||
@app.callback() | ||
def main(log_level: LogLevelType = "DEBUG"): | ||
logging.basicConfig( | ||
level=log_level, | ||
format="%(message)s", | ||
datefmt="[%X]", | ||
handlers=[RichHandler(rich_tracebacks=True)], | ||
) | ||
|
||
|
||
if __name__ == "__main__": | ||
app() |