mirror of
https://github.com/yrutschle/sslh.git
synced 2026-10-22 18:12:10 +03:00
support for max_connections on listen_endpoint for sslh-ev/sslh-select
This commit is contained in:
1 parent
65c9c4ce95
commit
4483e9c7e5
5 files changed
+65
-17
No files matched your search
@@ -109,6 +109,7 @@ struct connection {
|
||||
struct sslhcfg_protocols_item* proto; /* Where to connect to */
|
||||
|
||||
/* SOCK_STREAM */
|
||||
struct listen_endpoint* endpoint; /* Client-facing listen fd */
|
||||
enum connection_state state;
|
||||
time_t probe_timeout;
|
||||
|
||||
|
||||
+22
-13
@@ -22,22 +22,31 @@ connections:
|
||||
- Use `ulimit` (see bash(3) or your shell's man page) to
|
||||
limit the number of file descriptors.
|
||||
|
||||
- In `sslh-select` and `sslh-ev`, you can set
|
||||
`max_connections` per protocol, and `sslh` will drop
|
||||
connections after probing if the count is exceeded.
|
||||
This should help in keeping SSH connections available even
|
||||
if an attacker is stuffing other protocols. Currently this
|
||||
does not work for forking protocols (support is planned)
|
||||
Then, `sslh` provides several mechanisms to limit the number
|
||||
of concurrent connections, which in turns limits the number
|
||||
of file descriptors used.
|
||||
|
||||
- `sslh-fork` has an explicit design goal to be as simple as
|
||||
Essentially there are two ways to do this:
|
||||
|
||||
- you can set `max_connections` per protocol, and `sslh`
|
||||
will drop connections after probing if the count is
|
||||
exceeded. This should help in keeping SSH connections
|
||||
available even if an attacker is stuffing other protocols.
|
||||
Currently this does not work for forking protocols (support
|
||||
is planned).
|
||||
|
||||
- you can set `max_connections` for each `listen` entry. So
|
||||
the `sslh` process for each port will limit the number of
|
||||
concurrent connections to that port. This is similar to the
|
||||
`udp_max_connections` setting, but for TCP.
|
||||
|
||||
`sslh-select` and `sslh-ev` support both limit types.
|
||||
|
||||
`sslh-fork` has an explicit design goal to be as simple as
|
||||
possible, which makes it impossible to implement limits per
|
||||
protocol (because protocol probing is performed after the
|
||||
process has forked). Instead, you can set `max_connections`
|
||||
for each `listen` entry. So the `sslh` process for each port
|
||||
will limit the number of concurrent connections to that
|
||||
port. Currently this is not supported in `sslh-select` and
|
||||
`sslh-ev` (support is planned).
|
||||
|
||||
process has forked). Limits will only work for `listen`
|
||||
entries.
|
||||
|
||||
As of sslh 2.2.5, this is an experimental feature and not
|
||||
all use cases have been tested. If 2.2.5 does not exist yet,
|
||||
|
||||
+2
-1
@@ -50,6 +50,7 @@ int tidy_connection(struct connection *cnx, struct loop_info* fd_info)
|
||||
fd_info->num_probing--;
|
||||
|
||||
dec_connections(cnx);
|
||||
dec_listen_connections(cnx);
|
||||
|
||||
collection_remove_cnx(fd_info->collection, cnx);
|
||||
return 0;
|
||||
@@ -92,7 +93,7 @@ struct connection* cnx_accept_process(struct loop_info* fd_info, struct listen_e
|
||||
|
||||
switch (type) {
|
||||
case SOCK_STREAM:
|
||||
cnx = accept_new_connection(fd, fd_info);
|
||||
cnx = accept_new_connection(listen_socket, fd_info);
|
||||
if (!cnx) return NULL;
|
||||
|
||||
break;
|
||||
|
||||
+39
-2
@@ -118,12 +118,45 @@ void tcp_read_process(struct loop_info* fd_info,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* *cnx must have its endpoint field filled;
|
||||
* Increment the connection count for the listen endpoint.
|
||||
* Return 1 if connection count is exceeded, 0 otherwise */
|
||||
static int inc_listen_connections(struct connection* cnx)
|
||||
{
|
||||
cnx->endpoint->num_connections++;
|
||||
if (cnx->endpoint->endpoint_cfg->max_connections_is_present) {
|
||||
int num_cnx = cnx->endpoint->num_connections;
|
||||
int max_cnx = cnx->endpoint->endpoint_cfg->max_connections;
|
||||
|
||||
print_message(msg_connections, "Endpoint %d +1: %d/%d cnx\n",
|
||||
cnx->endpoint->socketfd, num_cnx, max_cnx);
|
||||
if (num_cnx > max_cnx) {
|
||||
print_message(msg_connections_error, "Endpoint %d: too many connections, dropping\n", cnx->endpoint->socketfd);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void dec_listen_connections(struct connection* cnx)
|
||||
{
|
||||
cnx->endpoint->num_connections--;
|
||||
print_message(msg_connections, "Endpoint %d -1: %d/%d cnx\n",
|
||||
cnx->endpoint->socketfd,
|
||||
cnx->endpoint->num_connections,
|
||||
cnx->endpoint->endpoint_cfg->max_connections);
|
||||
}
|
||||
|
||||
|
||||
/* Accepts a connection from the main socket and assigns it to an empty slot.
|
||||
* If no slots are available, allocate another few. If that fails, drop the
|
||||
* connexion */
|
||||
struct connection* accept_new_connection(int listen_socket, struct loop_info* fd_info)
|
||||
struct connection* accept_new_connection(struct listen_endpoint* endpoint, struct loop_info* fd_info)
|
||||
{
|
||||
int in_socket, res;
|
||||
int listen_socket = endpoint->socketfd;
|
||||
|
||||
print_message(msg_fd, "accepting from %d\n", listen_socket);
|
||||
|
||||
@@ -141,12 +174,16 @@ struct connection* accept_new_connection(int listen_socket, struct loop_info* fd
|
||||
close(in_socket);
|
||||
return NULL;
|
||||
}
|
||||
cnx->endpoint = endpoint;
|
||||
if (inc_listen_connections(cnx)) {
|
||||
tidy_connection(cnx, fd_info);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
add_probing_cnx(fd_info, cnx);
|
||||
return cnx;
|
||||
}
|
||||
|
||||
|
||||
/* Connect queue 1 of connection to SSL; returns new file descriptor */
|
||||
static int connect_queue(struct connection* cnx,
|
||||
struct loop_info* fd_info)
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
#include "tcp-probe.h"
|
||||
|
||||
void tcp_read_process(struct loop_info* fd_info, int fd);
|
||||
struct connection* accept_new_connection(int listen_socket, struct loop_info* fd_info);
|
||||
struct connection* accept_new_connection(struct listen_endpoint* endpoint, struct loop_info* fd_info);
|
||||
void probing_read_process(struct connection* cnx, struct loop_info* fd_info);
|
||||
void cnx_write_process(struct loop_info* fd_info, int fd);
|
||||
|
||||
|
||||
Reference in new issue
Block a user