Skip to content

Commit bccac8c

Browse files
committed
Add admin-port feature
Signed-off-by: hwware <[email protected]>
1 parent b5eb793 commit bccac8c

File tree

8 files changed

+98
-2
lines changed

8 files changed

+98
-2
lines changed

src/config.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3193,6 +3193,7 @@ standardConfig static_configs[] = {
31933193
/* Integer configs */
31943194
createIntConfig("databases", NULL, IMMUTABLE_CONFIG, 1, INT_MAX, server.dbnum, 16, INTEGER_CONFIG, NULL, NULL),
31953195
createIntConfig("port", NULL, MODIFIABLE_CONFIG, 0, 65535, server.port, 6379, INTEGER_CONFIG, NULL, updatePort), /* TCP port. */
3196+
createIntConfig("admin-port", NULL, IMMUTABLE_CONFIG, 0, 65535, server.admin_port, 0, INTEGER_CONFIG, NULL, NULL), /* TCP admin port. */
31963197
createIntConfig("io-threads", NULL, DEBUG_CONFIG | IMMUTABLE_CONFIG, 1, 128, server.io_threads_num, 1, INTEGER_CONFIG, NULL, NULL), /* Single threaded by default */
31973198
createIntConfig("events-per-io-thread", NULL, MODIFIABLE_CONFIG, 0, INT_MAX, server.events_per_io_thread, 2, INTEGER_CONFIG, NULL, NULL),
31983199
createIntConfig("prefetch-batch-max-size", NULL, MODIFIABLE_CONFIG, 0, 128, server.prefetch_batch_max_size, 16, INTEGER_CONFIG, NULL, NULL),

src/networking.c

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1389,6 +1389,7 @@ void clientAcceptHandler(connection *conn) {
13891389
void acceptCommonHandler(connection *conn, struct ClientFlags flags, char *ip) {
13901390
client *c;
13911391
UNUSED(ip);
1392+
int port;
13921393

13931394
if (connGetState(conn) != CONN_STATE_ACCEPTING) {
13941395
char addr[NET_ADDR_STR_LEN] = {0};
@@ -1401,12 +1402,26 @@ void acceptCommonHandler(connection *conn, struct ClientFlags flags, char *ip) {
14011402
return;
14021403
}
14031404

1405+
if (connAddrSockName(conn, NULL, 0, &port)) {
1406+
serverLog(LL_WARNING, "Unable to retrieve socket port");
1407+
connClose(conn);
1408+
return;
1409+
}
1410+
1411+
if (port == server.admin_port && connIsLocal(conn) != 1) {
1412+
serverLog(LL_WARNING, "Denied connection. On admin-port, connections are"
1413+
" only accepted from the loopback interface.");
1414+
server.stat_rejected_conn++;
1415+
connClose(conn);
1416+
return;
1417+
}
1418+
14041419
/* Limit the number of connections we take at the same time.
14051420
*
14061421
* Admission control will happen before a client is created and connAccept()
14071422
* called, because we don't want to even start transport-level negotiation
14081423
* if rejected. */
1409-
if (listLength(server.clients) + getClusterConnectionsCount() >= server.maxclients) {
1424+
if (port != server.admin_port && (listLength(server.clients) + getClusterConnectionsCount() >= server.maxclients)) {
14101425
char *err;
14111426
if (server.cluster_enabled)
14121427
err = "-ERR max number of clients + cluster "

src/server.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2821,6 +2821,25 @@ void initListeners(void) {
28212821
listener->priv2 = server.unixsocketgroup; /* Unix socket group specified */
28222822
}
28232823

2824+
if (server.admin_port != 0) {
2825+
conn_index = connectionIndexByType(CONN_TYPE_SOCKET);
2826+
if (conn_index < 0) serverPanic("Failed finding connection listener of %s", CONN_TYPE_SOCKET);
2827+
2828+
// Check if the current index is already occupied
2829+
while (server.listeners[conn_index].ct != NULL) {
2830+
conn_index++;
2831+
if (conn_index >= CONN_TYPE_MAX) {
2832+
serverPanic("No available index for additional TCP listener.");
2833+
}
2834+
}
2835+
2836+
listener = &server.listeners[conn_index];
2837+
listener->bindaddr = server.bindaddr;
2838+
listener->bindaddr_count = server.bindaddr_count;
2839+
listener->port = server.admin_port;
2840+
listener->ct = connectionByType(CONN_TYPE_SOCKET);
2841+
}
2842+
28242843
/* create all the configured listener, and add handler to start to accept */
28252844
int listen_fds = 0;
28262845
for (int j = 0; j < CONN_TYPE_MAX; j++) {

src/server.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1697,6 +1697,7 @@ struct valkeyServer {
16971697
_Atomic int module_gil_acquiring; /* Indicates whether the GIL is being acquiring by the main thread. */
16981698
/* Networking */
16991699
int port; /* TCP listening port */
1700+
int admin_port; /* TCP listening admin port */
17001701
int tls_port; /* TLS listening port */
17011702
int tcp_backlog; /* TCP listen() backlog */
17021703
char *bindaddr[CONFIG_BINDADDR_MAX]; /* Addresses we should bind to */

tests/support/server.tcl

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -534,7 +534,9 @@ proc start_server {options {code undefined}} {
534534
dict set config "tls-cluster" "yes"
535535
dict set config "tls-replication" "yes"
536536
} else {
537-
dict set config port $port
537+
set aport [find_available_port $::baseport $::portcount]
538+
dict set config "port" $port
539+
dict set config "admin-port" $aport
538540
}
539541

540542
set unixsocket [file normalize [format "%s/%s" [dict get $config "dir"] "socket"]]
@@ -604,7 +606,9 @@ proc start_server {options {code undefined}} {
604606
dict set config port $pport
605607
dict set config "tls-port" $port
606608
} else {
609+
set aport [find_available_port $::baseport $::portcount]
607610
dict set config port $port
611+
dict set config admin-port $aport
608612
}
609613
create_server_config_file $config_file $config $config_lines
610614

@@ -638,15 +642,18 @@ proc start_server {options {code undefined}} {
638642
# setup properties to be able to initialize a client object
639643
set port_param [expr $::tls ? {"tls-port"} : {"port"}]
640644
set host $::host
645+
set admin_port 0
641646
if {[dict exists $config bind]} { set host [lindex [dict get $config bind] 0] }
642647
if {[dict exists $config $port_param]} { set port [dict get $config $port_param] }
648+
if {[dict exists $config admin-port]} { set admin_port [lindex [dict get $config admin-port] 0] }
643649

644650
# setup config dict
645651
dict set srv "config_file" $config_file
646652
dict set srv "config" $config
647653
dict set srv "pid" $pid
648654
dict set srv "host" $host
649655
dict set srv "port" $port
656+
dict set srv "admin-port" $admin_port
650657
dict set srv "stdout" $stdout
651658
dict set srv "stderr" $stderr
652659
dict set srv "unixsocket" $unixsocket

tests/unit/admin-port.tcl

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
tags {external:skip tls:skip} {
2+
test {admin-port: CONFIG SET port number should fail} {
3+
start_server {} {
4+
set avail_port [find_available_port $::baseport $::portcount]
5+
set rd [valkey [srv 0 host] [srv 0 admin-port]]
6+
assert_error {*can't set immutable config*} {$rd CONFIG SET admin-port $avail_port}
7+
$rd PING
8+
$rd close
9+
}
10+
}
11+
12+
test {admin-port: connection should fail on non-loopback interface} {
13+
start_server {} {
14+
catch {valkey [get_nonloopback_addr] [srv 0 admin-port]} e
15+
assert_match {*connection refused*} $e
16+
}
17+
}
18+
19+
test {admin-port: setting admin-port to server port should fail} {
20+
start_server {} {
21+
catch {r CONFIG SET port [srv 0 admin-port]} e
22+
assert_match {*Unable to listen on this port*} $e
23+
}
24+
}
25+
26+
test {admin-port: client could connect on admin-port after maxclients reached} {
27+
start_server {} {
28+
set original_maxclients [lindex [r config get maxclients] 1]
29+
r config set maxclients 2
30+
set rd [valkey [srv 0 host] [srv 0 port]]
31+
assert_match "PONG" [$rd PING]
32+
set rd1 [valkey [srv 0 host] [srv 0 port]]
33+
catch {$rd1 PING} e
34+
assert_match "*ERR max*reached*" $e
35+
set rd2 [valkey [srv 0 host] [srv 0 admin-port]]
36+
assert_match "PONG" [$rd2 PING]
37+
r config set maxclients $original_maxclients
38+
$rd close
39+
$rd1 close
40+
$rd2 close
41+
}
42+
}
43+
}

tests/unit/introspection.tcl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -559,6 +559,7 @@ start_server {tags {"introspection"}} {
559559
req-res-logfile
560560
client-default-resp
561561
dual-channel-replication-enabled
562+
admin-port
562563
}
563564

564565
if {!$::tls} {

valkey.conf

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,15 @@ protected-mode yes
138138
# If port 0 is specified the server will not listen on a TCP socket.
139139
port 6379
140140

141+
# admin-port
142+
#
143+
# Accept connections on the specified port and connections should be originating from
144+
# local loopback (127.0.0.1), unix domain socket or IPv6 address (::1).
145+
# Default is 0 and immutable.
146+
# If admin-port is not specified the server will not listen on a TCP socket.
147+
#
148+
# admin-port 0
149+
141150
# TCP listen() backlog.
142151
#
143152
# In high requests-per-second environments you need a high backlog in order

0 commit comments

Comments
 (0)