add setting for maximum connection per protocol

This commit is contained in:
Yves Rutschle committed 2025-07-24 19:48:50 +02:00
1 parent 28ea73301e
commit feaf528a60
12 files changed
+85 -7

No files matched your search

+31
View File
@@ -595,6 +595,37 @@ void dump_connection(struct connection *cnx)
}
/* *cnx must have its proto field probed already.
* If required, increment the connection count for this protocol.
* Returns 1 if connection count is exceeded, 0 otherwise */
int inc_connections(struct connection* cnx)
{
if (cnx->proto->max_connections_is_present) {
cnx->proto->num_connections++;
print_message(msg_connections, "Proto %s +1: %d/%d cnx\n",
cnx->proto->name,
cnx->proto->num_connections,
cnx->proto->max_connections);
if (cnx->proto->num_connections > cnx->proto->max_connections) {
print_message(msg_connections_error, "%s: too many connections, dropping", cnx->proto->name);
return 1;
}
}
return 0;
}
void dec_connections(struct connection* cnx)
{
if (cnx->proto) {
cnx->proto->num_connections--;
print_message(msg_connections, "Proto %s -1: %d/%d cnx\n",
cnx->proto->name,
cnx->proto->num_connections,
cnx->proto->max_connections);
}
}
/*
* moves data from one fd to other
*
+2
View File
@@ -174,6 +174,8 @@ void drop_privileges(const char* user_name, const char* chroot_path);
void set_capabilities(int cap_net_admin);
void write_pid_file(const char* pidfile);
void dump_connection(struct connection *cnx);
int inc_connections(struct connection* cnx);
void dec_connections(struct connection* cnx);
int resolve_split_name(struct addrinfo **out, char* hostname, char* port);
int start_listen_sockets(struct listen_endpoint *sockfd[]);
+1 -1
View File
@@ -1,5 +1,5 @@
/* Generated by conf2struct (https://www.rutschle.net/tech/conf2struct/README)
* on Sun Apr 6 11:44:59 2025.
* on Wed Jul 16 17:59:23 2025.
# conf2struct: generate libconf parsers that read to structs
# Copyright (C) 2018-2024 Yves Rutschle
+1 -1
View File
@@ -1,5 +1,5 @@
/* Generated by conf2struct (https://www.rutschle.net/tech/conf2struct/README)
* on Sun Apr 6 11:44:59 2025.
* on Wed Jul 16 17:59:23 2025.
# conf2struct: generate libconf parsers that read to structs
# Copyright (C) 2018-2024 Yves Rutschle
+5 -1
View File
@@ -70,7 +70,11 @@ listen:
# keepalive: Should TCP keepalive be on or off for that
# connection (default is off)
# fork: Should a new process be forked for this protocol?
# (only useful for sslh-select)
# (only useful for sslh-select and sslh-ev)
# max_connections: further connections for this protocol
# will be rejected once the limit is reached. Does not
# work when fork is used (either in sslh-fork or if the
# previous option is set).
# tfo_ok: Set to true if the server supports TCP FAST OPEN
# resolve_on_forward: Set to true if server address should be resolved on
# (every) newly incoming connection (again)
+2
View File
@@ -49,6 +49,8 @@ int tidy_connection(struct connection *cnx, struct loop_info* fd_info)
if (gap_remove_ptr(fd_info->probing_list, cnx, fd_info->num_probing) != -1)
fd_info->num_probing--;
dec_connections(cnx);
collection_remove_cnx(fd_info->collection, cnx);
return 0;
}
+23 -2
View File
@@ -1,5 +1,5 @@
/* Generated by conf2struct (https://www.rutschle.net/tech/conf2struct/README)
* on Sun Apr 6 11:44:58 2025.
* on Wed Jul 16 17:59:23 2025.
# conf2struct: generate libconf parsers that read to structs
# Copyright (C) 2018-2024 Yves Rutschle
@@ -500,7 +500,7 @@ struct arg_file* sslhcfg_conffile;
struct arg_str* sslhcfg_anyprot;
struct arg_end* sslhcfg_end;
static struct config_desc table_sslhcfg_protocols[] = {
@@ -712,6 +712,22 @@ static struct config_desc table_sslhcfg_protocols[] = {
/* default_val*/ .default_val.def_bool = 0
},
{
/* name */ "max_connections",
/* type */ CFG_INT,
/* sub_group*/ NULL,
/* arg_cl */ NULL,
/* base_addr */ NULL,
/* offset */ offsetof(struct sslhcfg_protocols_item, max_connections),
/* offset_len */ 0,
/* offset_present */ offsetof(struct sslhcfg_protocols_item, max_connections_is_present),
/* size */ sizeof(int),
/* array_type */ -1,
/* mandatory */ 0,
/* optional */ 1,
/* default_val*/ .default_val.def_int = 0
},
{
/* name */ "sni_hostnames",
/* type */ CFG_ARRAY,
@@ -2421,6 +2437,11 @@ static void sslhcfg_protocols_fprint(
fprintf(out, "keepalive: %d", sslhcfg_protocols->keepalive);
fprintf(out, "\n");
indent(out, depth);
fprintf(out, "max_connections: %d", sslhcfg_protocols->max_connections);
if (! sslhcfg_protocols->max_connections_is_present)
fprintf(out, " <unset>");
fprintf(out, "\n");
indent(out, depth);
fprintf(out, "sni_hostnames [%zu]:\n", sslhcfg_protocols->sni_hostnames_len);
for (i = 0; i < sslhcfg_protocols->sni_hostnames_len; i++) {
indent(out, depth+1);
+4 -1
View File
@@ -1,5 +1,5 @@
/* Generated by conf2struct (https://www.rutschle.net/tech/conf2struct/README)
* on Sun Apr 6 11:44:58 2025.
* on Wed Jul 16 17:59:23 2025.
# conf2struct: generate libconf parsers that read to structs
# Copyright (C) 2018-2024 Yves Rutschle
@@ -63,6 +63,8 @@ struct sslhcfg_protocols_item {
int resolve_on_forward;
int log_level;
int keepalive;
int max_connections_is_present;
int max_connections;
size_t sni_hostnames_len;
char** sni_hostnames;
size_t alpn_protocols_len;
@@ -76,6 +78,7 @@ struct sslhcfg_protocols_item {
T_PROBE* probe;
struct addrinfo* saddr;
void* data;
unsigned int num_connections;
dl_list timeouts;
};
+2
View File
@@ -123,6 +123,7 @@ config: {
description: "Set to true if server address should be resolved on (every) newly incoming connection (again)" },
{ name: "log_level"; type: "int"; default: 1 },
{ name: "keepalive"; type: "bool"; default: false },
{ name: "max_connections"; type: "int"; optional: true },
{ name: "sni_hostnames",
type: "array",
element_type: "string"
@@ -142,6 +143,7 @@ config: {
{ name: "probe"; type: "runtime"; c_type: "T_PROBE*" },
{ name: "saddr"; type: "runtime"; c_type: "struct addrinfo*" },
{ name: "data"; type: "runtime"; c_type: "void*" },
{ name: "num_connections"; type: "runtime"; c_type: "unsigned int" },
{ name: "timeouts"; type: "runtime"; c_type: "dl_list" }
)
}
+5
View File
@@ -276,6 +276,11 @@ void probing_read_process(struct connection* cnx,
remove_probing_cnx(fd_info, cnx);
cnx->state = ST_SHOVELING;
if (inc_connections(cnx)) {
tidy_connection(cnx, fd_info);
return;
}
/* libwrap check if required for this protocol */
if (cnx->proto->service &&
check_access_rights(cnx->q[0].fd, cnx->proto->service)) {
+4 -1
View File
@@ -43,7 +43,8 @@ listen:
protocols:
(
{ name: "ssh"; host: "localhost"; port: "9000"; fork: true; transparent: true; resolve_on_forward: true; },
{ name: "ssh"; host: "localhost"; port: "9000"; fork: true; transparent: true; resolve_on_forward: true;
max_connections: 1; },
{ name: "socks5"; host: "localhost"; port: "9001"; },
{ name: "http"; host: "localhost"; port: "80"; proxyprotocol: 2; },
{ name: "tinc"; host: "localhost"; port: "9003"; },
@@ -52,6 +53,7 @@ protocols:
{ name: "adb"; host: "localhost"; port: "9010"; },
{ name: "syslog"; host: "localhost"; port: "9013"; },
{ name: "regex"; host: "ip4-localhost"; is_udp: true; port: "9020";
max_connections: 1;
udp_timeout: 30;
regex_patterns: [ "^foo" ];
resolve_on_forward: true;
@@ -72,6 +74,7 @@ protocols:
{ name: "tls"; host: "localhost"; port: "9023"; alpn_protocols: [ "alpn3" ]; },
{ name: "tls"; host: "localhost"; port: "9024"; sni_hostnames: [ "sni3" ]; },
{ name: "tls"; host: "localhost"; port: "9025"; },
{ name: "anyprot"; host: "ip4-localhost"; is_udp: true; port: "9999"; },
{ name: "anyprot"; host: "localhost"; port: "9099"; }
);
+5
View File
@@ -302,6 +302,11 @@ struct connection* udp_c2s_forward(int sockfd, struct loop_info* fd_info)
cnx->addrlen = addrlen;
cnx->local_endpoint = sockfd;
if (inc_connections(cnx)) {
tidy_connection(cnx, fd_info);
return NULL;
}
res = new_source(fd_info->hash_sources, cnx);
if (res == -1) {
print_message(msg_connections_error, "Out of hash space for new incoming UDP connection -- increase udp_max_connections");