Merge pull request #7756 from wizrds/feat/secure-ws-conn
Support SSL in WebSocket connection
This commit is contained in:
commit
7785c91c5d
@ -21,6 +21,7 @@ Enable subscribing to an instance by adding the `external_message_consumer` sect
|
|||||||
"name": "default", // This can be any name you'd like, default is "default"
|
"name": "default", // This can be any name you'd like, default is "default"
|
||||||
"host": "127.0.0.1", // The host from your producer's api_server config
|
"host": "127.0.0.1", // The host from your producer's api_server config
|
||||||
"port": 8080, // The port from your producer's api_server config
|
"port": 8080, // The port from your producer's api_server config
|
||||||
|
"secure": false, // Use a secure websockets connection, default false
|
||||||
"ws_token": "sercet_Ws_t0ken" // The ws_token from your producer's api_server config
|
"ws_token": "sercet_Ws_t0ken" // The ws_token from your producer's api_server config
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -42,6 +43,7 @@ Enable subscribing to an instance by adding the `external_message_consumer` sect
|
|||||||
| `producers.name` | **Required.** Name of this producer. This name must be used in calls to `get_producer_pairs()` and `get_producer_df()` if more than one producer is used.<br> **Datatype:** string
|
| `producers.name` | **Required.** Name of this producer. This name must be used in calls to `get_producer_pairs()` and `get_producer_df()` if more than one producer is used.<br> **Datatype:** string
|
||||||
| `producers.host` | **Required.** The hostname or IP address from your producer.<br> **Datatype:** string
|
| `producers.host` | **Required.** The hostname or IP address from your producer.<br> **Datatype:** string
|
||||||
| `producers.port` | **Required.** The port matching the above host.<br> **Datatype:** string
|
| `producers.port` | **Required.** The port matching the above host.<br> **Datatype:** string
|
||||||
|
| `producers.secure` | **Optional.** Use ssl in websockets connection. Default False.<br> **Datatype:** string
|
||||||
| `producers.ws_token` | **Required.** `ws_token` as configured on the producer.<br> **Datatype:** string
|
| `producers.ws_token` | **Required.** `ws_token` as configured on the producer.<br> **Datatype:** string
|
||||||
| | **Optional settings**
|
| | **Optional settings**
|
||||||
| `wait_timeout` | Timeout until we ping again if no message is received. <br>*Defaults to `300`.*<br> **Datatype:** Integer - in seconds.
|
| `wait_timeout` | Timeout until we ping again if no message is received. <br>*Defaults to `300`.*<br> **Datatype:** Integer - in seconds.
|
||||||
|
@ -389,6 +389,44 @@ Now anytime those types of RPC messages are sent in the bot, you will receive th
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Reverse Proxy setup
|
||||||
|
|
||||||
|
When using [Nginx](https://nginx.org/en/docs/), the following configuration is required for WebSockets to work (Note this configuration is incomplete, it's missing some information and can not be used as is):
|
||||||
|
|
||||||
|
Please make sure to replace `<freqtrade_listen_ip>` (and the subsequent port) with the IP and Port matching your configuration/setup.
|
||||||
|
|
||||||
|
```
|
||||||
|
http {
|
||||||
|
map $http_upgrade $connection_upgrade {
|
||||||
|
default upgrade;
|
||||||
|
'' close;
|
||||||
|
}
|
||||||
|
|
||||||
|
#...
|
||||||
|
|
||||||
|
server {
|
||||||
|
#...
|
||||||
|
|
||||||
|
location / {
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_pass http://<freqtrade_listen_ip>:8080;
|
||||||
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
|
proxy_set_header Connection $connection_upgrade;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
To properly configure your reverse proxy (securely), please consult it's documentation for proxying websockets.
|
||||||
|
|
||||||
|
- **Traefik**: Traefik supports websockets out of the box, see the [documentation](https://doc.traefik.io/traefik/)
|
||||||
|
- **Caddy**: Caddy v2 supports websockets out of the box, see the [documentation](https://caddyserver.com/docs/v2-upgrade#proxy)
|
||||||
|
|
||||||
|
!!! Tip "SSL certificates"
|
||||||
|
You can use tools like certbot to setup ssl certificates to access your bot's UI through encrypted connection by using any fo the above reverse proxies.
|
||||||
|
While this will protect your data in transit, we do not recommend to run the freqtrade API outside of your private network (VPN, SSH tunnel).
|
||||||
|
|
||||||
### OpenAPI interface
|
### OpenAPI interface
|
||||||
|
|
||||||
To enable the builtin openAPI interface (Swagger UI), specify `"enable_openapi": true` in the api_server configuration.
|
To enable the builtin openAPI interface (Swagger UI), specify `"enable_openapi": true` in the api_server configuration.
|
||||||
|
@ -512,6 +512,7 @@ CONF_SCHEMA = {
|
|||||||
'minimum': 0,
|
'minimum': 0,
|
||||||
'maximum': 65535
|
'maximum': 65535
|
||||||
},
|
},
|
||||||
|
'secure': {'type': 'boolean', 'default': False},
|
||||||
'ws_token': {'type': 'string'},
|
'ws_token': {'type': 'string'},
|
||||||
},
|
},
|
||||||
'required': ['name', 'host', 'ws_token']
|
'required': ['name', 'host', 'ws_token']
|
||||||
|
@ -31,6 +31,7 @@ class Producer(TypedDict):
|
|||||||
name: str
|
name: str
|
||||||
host: str
|
host: str
|
||||||
port: int
|
port: int
|
||||||
|
secure: bool
|
||||||
ws_token: str
|
ws_token: str
|
||||||
|
|
||||||
|
|
||||||
@ -180,7 +181,8 @@ class ExternalMessageConsumer:
|
|||||||
host, port = producer['host'], producer['port']
|
host, port = producer['host'], producer['port']
|
||||||
token = producer['ws_token']
|
token = producer['ws_token']
|
||||||
name = producer['name']
|
name = producer['name']
|
||||||
ws_url = f"ws://{host}:{port}/api/v1/message/ws?token={token}"
|
scheme = 'wss' if producer.get('secure', False) else 'ws'
|
||||||
|
ws_url = f"{scheme}://{host}:{port}/api/v1/message/ws?token={token}"
|
||||||
|
|
||||||
# This will raise InvalidURI if the url is bad
|
# This will raise InvalidURI if the url is bad
|
||||||
async with websockets.connect(
|
async with websockets.connect(
|
||||||
|
@ -199,6 +199,7 @@ async def create_client(
|
|||||||
host,
|
host,
|
||||||
port,
|
port,
|
||||||
token,
|
token,
|
||||||
|
scheme='ws',
|
||||||
name='default',
|
name='default',
|
||||||
protocol=ClientProtocol(),
|
protocol=ClientProtocol(),
|
||||||
sleep_time=10,
|
sleep_time=10,
|
||||||
@ -211,13 +212,14 @@ async def create_client(
|
|||||||
:param host: The host
|
:param host: The host
|
||||||
:param port: The port
|
:param port: The port
|
||||||
:param token: The websocket auth token
|
:param token: The websocket auth token
|
||||||
|
:param scheme: `ws` for most connections, `wss` for ssl
|
||||||
:param name: The name of the producer
|
:param name: The name of the producer
|
||||||
:param **kwargs: Any extra kwargs passed to websockets.connect
|
:param **kwargs: Any extra kwargs passed to websockets.connect
|
||||||
"""
|
"""
|
||||||
|
|
||||||
while 1:
|
while 1:
|
||||||
try:
|
try:
|
||||||
websocket_url = f"ws://{host}:{port}/api/v1/message/ws?token={token}"
|
websocket_url = f"{scheme}://{host}:{port}/api/v1/message/ws?token={token}"
|
||||||
logger.info(f"Attempting to connect to {name} @ {host}:{port}")
|
logger.info(f"Attempting to connect to {name} @ {host}:{port}")
|
||||||
|
|
||||||
async with websockets.connect(websocket_url, **kwargs) as ws:
|
async with websockets.connect(websocket_url, **kwargs) as ws:
|
||||||
@ -304,6 +306,7 @@ async def _main(args):
|
|||||||
producer['host'],
|
producer['host'],
|
||||||
producer['port'],
|
producer['port'],
|
||||||
producer['ws_token'],
|
producer['ws_token'],
|
||||||
|
'wss' if producer.get('secure', False) else 'ws',
|
||||||
producer['name'],
|
producer['name'],
|
||||||
sleep_time=sleep_time,
|
sleep_time=sleep_time,
|
||||||
ping_timeout=ping_timeout,
|
ping_timeout=ping_timeout,
|
||||||
|
Loading…
Reference in New Issue
Block a user