asyncio-socks-server
A SOCKS proxy server implemented with the powerful python cooperative concurrency framework asyncio.
Features
- Supports both TCP and UDP with the implementation of SOCKS5 protocol
- Supports username/password authentication
- Provides optional strict mode that follows RFC1928 and RFC1929 without compromise
- Driven by the python standard library, no third-party dependencies
Installation
Install with pip if Python version 3.8.0 or higher is available.
pip install asyncio-socks-server
Or pull a docker image from the Docker Hub registry.
docker pull amaindex/asyncio-socks-server
Usage
When installed with pip, you can invoke asyncio-socks-server from the command-line:
asyncio_socks_server [-h] [-v]
[-H HOST] [-P PORT] [-A METHOD]
[--access-log] [--debug] [--strict]
[--env-prefix ENV_PREFIX]
[--config PATH]
where:
asyncio_socks_server
: You could use python -m asyncio_socks_server in development.-h
, --help
: Show a help message and exit.-v
, --version
: Show program's version number and exit.-H HOST
, --host HOST
: Host address to listen (default 0.0.0.0).-P PORT
, --port PORT
: Port to listen (default 1080).-A METHOD
, --auth METHOD
: Authentication method (default 0).
Possible values: 0 (no auth), 2 (username/password auth)--access-log
: Display access log.--debug
: Work in debug mode.--strict
: Work in strict compliance with RFC1928 and RFC1929.
If the value of METHOD
is 2, that is, when the username/password authentication
is specified, you need to provide a config file containing the usernames and passwords
in json format with the --config
option.
You can also list other options in the config file instead of the command:
config.json
:
{
"LISTEN_HOST": "0.0.0.0",
"LISTEN_PORT": 1080,
"AUTH_METHOD": 2,
"ACCESS_LOG": true,
"DEBUG": true,
"STRICT": true,
"USERS": {
"username1": "password1",
"username2": "password2",
"username3": "password3"
}
}
asyncio_socks_server --config ${ENV}/config.json
In addition, any environment variable named starting with AIOSS_
will also be applied
to the option.
The prefix can be changed by specifying the --env-prefix
option,for example:
export MY_LISTEN_HOST=127.0.0.1
export MY_LISTEN_PORT=9999
asyncio_socks_server --env-prefix MY_
NOTE: The loading order of the options is: config file, environment variables, command options.
The latter will overwrite the former if options are given in multiple ways.
Alternatively, if you use the docker image, you can launch the asyncio-socks-server with the following command:
docker run amaindex/asyncio-socks-server [-h] [-v]
[-H HOST] [-P PORT] [-A METHOD]
[--access-log] [--debug] [--strict]
[--env-prefix ENV_PREFIX]
[--config PATH]
The network mode host
is recommended since asyncio-socks-server uses multiple ports dynamically.
If you also want to provide a config file, it should be mounted manually.
docker run \
--rm \
--net=host \
-v /host/path/config.json:/config.json \
amaindex/asyncio-socks-server \
--config /config.json
Strict Mode
For various reasons, asyncio-socks-server has made some compromises on the
Implementation details of the protocols. Therefore, in the following scenes,
asyncio-socks-server’s behavior will be divergent from that described in RFC1928
and RFC1929.
asyncio-socks-server relays all UDP datagrams by default
In the SOCKS5 negotiation, a UDP ASSOCIATE request formed as follows is used to
establish an association within the UDP relay process to handle UDP datagrams:
+----+-----+-------+------+----------+----------+
|VER | CMD | RSV | ATYP | DST.ADDR | DST.PORT |
+----+-----+-------+------+----------+----------+
| 1 | 1 | X'00' | 1 | Variable | 2 |
+----+-----+-------+------+----------+----------+
Normally, the DST.ADDR and DST.PORT fields contain the address and port that the
client expects to use to send UDP datagrams on for the association, or use a port number
and address of all zeros if the client does not possess this information.
Therefore, when the client is working in a network that uses NAT, the DST.ADDR
with all zeros should be used to avoid errors. But in case some clients
did not follow this principle correctly, asyncio-socks-server relays all UDP datagrams
it receives by default instead of using DST.ADDR and DST.PORT to limit the access.
asyncio-socks-server allows "V5" username/password authentication
Once the client selects the username/password authentication during negotiation,
it will conduct a sub-negotiation with the server. This sub-negotiation begins with
the client producing a request:
+----+------+----------+------+----------+
|VER | ULEN | UNAME | PLEN | PASSWD |
+----+------+----------+------+----------+
| 1 | 1 | 1 to 255 | 1 | 1 to 255 |
+----+------+----------+------+----------+
The VER field contains the current version of the sub-negotiation, which is X'01' but
often considered as X'05' since it's a bit counter-intuitive.
So asyncio-socks-server allows requests with VER X'05' in non-strict mode.
--strict
option
To disable the compromise described above, you can specify the --strict
option:
asyncio_socks_server --strict
Reference