mirror of
https://github.com/processone/ejabberd.git
synced 2024-11-24 16:23:40 +01:00
ejabberdctl: support concurrent connections with bound conn names
If flock is available, ejabberdctl will use it to grab one of a bound number of connection names. This allows concurrent connections while using a bound number of atoms. Using PID, timestamps or random strings for transient connection IDs (which would avoid the need for flock) uses an unbound number of atoms. This can effectively DoS servers, as these connection names are not garbage collected.
This commit is contained in:
parent
8bd37462cb
commit
10c16b1cdf
@ -110,6 +110,9 @@ MSGSDIR = $(PRIVDIR)/msgs
|
|||||||
# /var/lib/ejabberd/
|
# /var/lib/ejabberd/
|
||||||
SPOOLDIR = $(DESTDIR)@localstatedir@/lib/ejabberd
|
SPOOLDIR = $(DESTDIR)@localstatedir@/lib/ejabberd
|
||||||
|
|
||||||
|
# /var/lock/ejabberdctl
|
||||||
|
CTLLOCKDIR = $(DESTDIR)@localstatedir@/lock/ejabberdctl
|
||||||
|
|
||||||
# /var/lib/ejabberd/.erlang.cookie
|
# /var/lib/ejabberd/.erlang.cookie
|
||||||
COOKIEFILE = $(SPOOLDIR)/.erlang.cookie
|
COOKIEFILE = $(SPOOLDIR)/.erlang.cookie
|
||||||
|
|
||||||
@ -230,6 +233,12 @@ install: all
|
|||||||
install -d -m 750 $(O_USER) $(SPOOLDIR)
|
install -d -m 750 $(O_USER) $(SPOOLDIR)
|
||||||
$(CHOWN_COMMAND) -R @INSTALLUSER@ $(SPOOLDIR) >$(CHOWN_OUTPUT)
|
$(CHOWN_COMMAND) -R @INSTALLUSER@ $(SPOOLDIR) >$(CHOWN_OUTPUT)
|
||||||
chmod -R 750 $(SPOOLDIR)
|
chmod -R 750 $(SPOOLDIR)
|
||||||
|
|
||||||
|
# ejabberdctl lock directory
|
||||||
|
install -d -m 750 $(O_USER) $(CTLLOCKDIR)
|
||||||
|
$(CHOWN_COMMAND) -R @INSTALLUSER@ $(CTLLOCKDIR) >$(CHOWN_OUTPUT)
|
||||||
|
chmod -R 750 $(CTLLOCKDIR)
|
||||||
|
|
||||||
[ ! -f $(COOKIEFILE) ] || { $(CHOWN_COMMAND) @INSTALLUSER@ $(COOKIEFILE) >$(CHOWN_OUTPUT) ; chmod 400 $(COOKIEFILE) ; }
|
[ ! -f $(COOKIEFILE) ] || { $(CHOWN_COMMAND) @INSTALLUSER@ $(COOKIEFILE) >$(CHOWN_OUTPUT) ; chmod 400 $(COOKIEFILE) ; }
|
||||||
#
|
#
|
||||||
# Log directory
|
# Log directory
|
||||||
@ -265,6 +274,7 @@ uninstall-all: uninstall-binary
|
|||||||
rm -rf $(ETCDIR)
|
rm -rf $(ETCDIR)
|
||||||
rm -rf $(EJABBERDDIR)
|
rm -rf $(EJABBERDDIR)
|
||||||
rm -rf $(SPOOLDIR)
|
rm -rf $(SPOOLDIR)
|
||||||
|
rm -rf $(CTLLOCKDIR)
|
||||||
rm -rf $(LOGDIR)
|
rm -rf $(LOGDIR)
|
||||||
|
|
||||||
clean: clean-recursive clean-local
|
clean: clean-recursive clean-local
|
||||||
|
@ -14,6 +14,17 @@ ERLANG_NODE=$NODE@$HOST
|
|||||||
ERL=@erl@
|
ERL=@erl@
|
||||||
INSTALLUSER=@installuser@
|
INSTALLUSER=@installuser@
|
||||||
|
|
||||||
|
# Control number of connections identifiers
|
||||||
|
# using flock if available. Expects a linux-style
|
||||||
|
# flock that can lock a file descriptor.
|
||||||
|
MAXCONNID=100
|
||||||
|
CONNLOCKDIR=@LOCALSTATEDIR@/lock/ejabberdctl
|
||||||
|
FLOCK='/usr/bin/flock'
|
||||||
|
if [ ! -x "$FLOCK" ];then
|
||||||
|
FLOCK=""
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
# parse command line parameters
|
# parse command line parameters
|
||||||
ARGS=
|
ARGS=
|
||||||
while [ $# -ne 0 ] ; do
|
while [ $# -ne 0 ] ; do
|
||||||
@ -228,13 +239,54 @@ help ()
|
|||||||
ctl ()
|
ctl ()
|
||||||
{
|
{
|
||||||
COMMAND=$@
|
COMMAND=$@
|
||||||
$EXEC_CMD "$ERL \
|
|
||||||
$NAME ctl-${ERLANG_NODE} \
|
if [ ! "$FLOCK" ];then
|
||||||
-noinput \
|
# no flock, simply invoke ctlexec()
|
||||||
-hidden \
|
CTL_CONN="ctl-${EJABBERD_NODE}"
|
||||||
-pa $EJABBERD_EBIN_PATH \
|
ctlexec $CTL_CONN $COMMAND
|
||||||
-s ejabberd_ctl -extra $ERLANG_NODE $COMMAND"
|
|
||||||
result=$?
|
result=$?
|
||||||
|
else
|
||||||
|
# we have flock so we get a lock
|
||||||
|
# on one of a limited number of
|
||||||
|
# conn names -- this allows
|
||||||
|
# concurrent invokations using a bound
|
||||||
|
# number of atoms
|
||||||
|
for N in $(seq 1 $MAXCONNID); do
|
||||||
|
CTL_CONN="ejabberdctl-$N"
|
||||||
|
CTL_LOCKFILE="$CONNLOCKDIR/$CTL_CONN"
|
||||||
|
(
|
||||||
|
exec 8>"$CTL_LOCKFILE"
|
||||||
|
if flock --nb 8; then
|
||||||
|
ctlexec $CTL_CONN $COMMAND
|
||||||
|
ssresult=$?
|
||||||
|
# segregate from possible flock exit(1)
|
||||||
|
ssresult=$(expr $ssresult \* 10)
|
||||||
|
exit $ssresult
|
||||||
|
else
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
)
|
||||||
|
result=$?
|
||||||
|
if [ $result -eq 1 ]; then
|
||||||
|
# means we errored out in flock
|
||||||
|
# rather than in the exec - stay in the loop
|
||||||
|
# trying other conn names...
|
||||||
|
badlock=1
|
||||||
|
else
|
||||||
|
badlock=""
|
||||||
|
break;
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
result=$(expr $result / 10)
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$badlock" ];then
|
||||||
|
echo "Ran out of connections to try. Your ejabberd processes" >&2
|
||||||
|
echo "may be stuck or this is a very busy server. For very" >&2
|
||||||
|
echo "busy servers, consider raising MAXCONNIDS" >&2
|
||||||
|
exit 1;
|
||||||
|
fi
|
||||||
|
|
||||||
case $result in
|
case $result in
|
||||||
0) :;;
|
0) :;;
|
||||||
1) :;;
|
1) :;;
|
||||||
@ -244,6 +296,18 @@ ctl ()
|
|||||||
return $result
|
return $result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ctlexec ()
|
||||||
|
{
|
||||||
|
CONN_NAME=$1; shift
|
||||||
|
COMMAND=$@
|
||||||
|
$EXEC_CMD "$ERL \
|
||||||
|
$NAME ${CONN_NAME} \
|
||||||
|
-noinput \
|
||||||
|
-hidden \
|
||||||
|
-pa $EJABBERD_EBIN_PATH \
|
||||||
|
-s ejabberd_ctl -extra $ERLANG_NODE $COMMAND"
|
||||||
|
}
|
||||||
|
|
||||||
# display ctl usage
|
# display ctl usage
|
||||||
usage ()
|
usage ()
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user