Skip to content

Commit

Permalink
Connection tracking - Work around Openvpn issue #160
Browse files Browse the repository at this point in the history
Details:
* #213
* https://community.openvpn.net/openvpn/ticket/160

Signed-off-by: Richard T Bonhomme <tincantech@protonmail.com>
  • Loading branch information
TinCanTech committed Oct 11, 2021
1 parent 7bc0683 commit 9864cfa
Show file tree
Hide file tree
Showing 3 changed files with 173 additions and 57 deletions.
86 changes: 63 additions & 23 deletions easytls-client-connect.sh
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ help_text ()
-p|--push-required Require all clients to use --push-peer-info.
-c|--crypt-v2-required Require all clients to use a TLS-Crypt-V2 key.
-k|--key-required Require all client keys to have a hardware-address.
-d|--dyn-opts=<FILE> Path and name of Openvpn client dynamic options file.
-t|--tmp-dir=<DIR> Temp directory where server-scripts write data.
Default: *nix /tmp/easytls
Windows C:/Windows/Temp/easytls
Expand Down Expand Up @@ -269,10 +270,9 @@ deps ()
EASYTLS_KILL_FILE="${temp_stub}-kill-client"

# Dynamic opts file
EASYTLS_DYN_OPTS_FILE="${temp_stub}-dyn-opts"
if [ -f "${EASYTLS_DYN_OPTS_FILE}" ]
if [ -f "${EASYTLS_DYN_OPTS_FILE}" ] && [ -n "${ovpn_dyn_opts_file}" ]
then
"${EASYTLS_CAT}" "${EASYTLS_DYN_OPTS_FILE}" > "${ovpn_cli_dyn_file}"
"${EASYTLS_CAT}" "${EASYTLS_DYN_OPTS_FILE}" > "${ovpn_dyn_opts_file}"
update_status "dyn opts loaded"
fi
}
Expand Down Expand Up @@ -302,6 +302,11 @@ do
empty_ok=1
EASYTLS_VERBOSE=1
;;
-d|--dyn-opts)
EASYTLS_DYN_OPTS_FILE="${val}"
[ -f "${EASYTLS_DYN_OPTS_FILE}" ] || \
warn_die "Easy-TLS dynamic opts file missing"
;;
-a|--allow-no-check)
empty_ok=1
allow_no_check=1
Expand Down Expand Up @@ -340,7 +345,7 @@ do
then
# Do not need this in the log but keep it here for reference
#[ $EASYTLS_VERBOSE ] && echo "Ignoring temp file: $opt"
ovpn_cli_dyn_file="${opt}"
ovpn_dyn_opts_file="${opt}"
else
[ "${EASYTLS_VERBOSE}" ] && warn_die "Unknown option: ${opt}"
fi
Expand Down Expand Up @@ -380,21 +385,6 @@ deps
unset env_file
}

# Source conn-trac lib
[ $ENABLE_CONN_TRAC ] && {
prog_dir="${0%/*}"
lib_file="${prog_dir}/easytls-conntrac.lib"
[ -f "${lib_file}" ] || {
easytls_url="https://github.com/TinCanTech/easy-tls"
easytls_wiki="/wiki/download-and-install"
#easytls_rawurl="https://raw.githubusercontent.com/TinCanTech/easy-tls"
#easytls_file="/master/easytls-conntrac.lib"
help_note="See: ${easytls_url}${easytls_wiki}"
die "Missing ${lib_file}"
}
. "${lib_file}"
unset lib_file
}

# flush auth-control file
#"${EASYTLS_RM}" -f "${auth_control_file}"
Expand All @@ -415,16 +405,66 @@ client_serial="$(format_number "${tls_serial_hex_0}")"
}

# Update connection tracking
[ $ENABLE_CONN_TRAC ] && {
if [ $ENABLE_CONN_TRAC ]
then
prog_dir="${0%/*}"
lib_file="${prog_dir}/easytls-conntrac.lib"
[ -f "${lib_file}" ] || {
easytls_url="https://github.com/TinCanTech/easy-tls"
easytls_wiki="/wiki/download-and-install"
#easytls_rawurl="https://raw.githubusercontent.com/TinCanTech/easy-tls"
#easytls_file="/master/easytls-conntrac.lib"
help_note="See: ${easytls_url}${easytls_wiki}"
die "Missing ${lib_file}"
}
. "${lib_file}"
unset lib_file

conntrac_record="${UV_TLSKEY_SERIAL:-TLSAC}"
conntrac_record="${conntrac_record}=${client_serial}=${common_name}"
# shellcheck disable=SC2154
conntrac_record="${conntrac_record}=${ifconfig_pool_remote_ip}"
# shellcheck disable=SC2154
conntrac_record="${conntrac_record}++${untrusted_ip}:${untrusted_port}"

conn_trac_connect "${conntrac_record}" "${EASYTLS_CONN_TRAC}" || {
update_status "conn_trac_connect FAIL"
[ $FATAL_CONN_TRAC ] && die "CONNTRAC_CONNECT_FAIL" 99
case $? in
2) update_status "conn_trac_connect ERROR"
conntrac_error=1
;;
1)
update_status "conn_trac_connect FAIL"
[ $FATAL_CONN_TRAC ] && die "CONNTRAC_CONNECT_FAIL" 99
;;
*) die "CONNTRAC_CONNECT_FAIL" 98 ;;
esac
conntrac_fail=1
}
}

# Log failure
if [ $conntrac_fail ]
then
{
[ -f "${EASYTLS_CONN_TRAC}.fail" ] && \
"${EASYTLS_CAT}" "${EASYTLS_CONN_TRAC}.fail"
"${EASYTLS_PRINTF}" '%s ' "$(date '+%x %X')"
[ $conntrac_error ] && "${EASYTLS_PRINTF}" '%s ' "AR"
"${EASYTLS_PRINTF}" '%s\n' "CON: ${conntrac_record}"
} > "${EASYTLS_CONN_TRAC}.fail.tmp"
"${EASYTLS_MV}" "${EASYTLS_CONN_TRAC}.fail.tmp" \
"${EASYTLS_CONN_TRAC}.fail"

env_file="${temp_stub}-client-connect.env"
if [ $EASYTLS_FOR_WINDOWS ]; then
set > "${env_file}"
else
env > "${env_file}"
fi
unset env_file
fi
else
update_status "conn-trac disabled"
fi

# Check for kill signal
if [ -f "${EASYTLS_KILL_FILE}" ] && \
Expand Down
112 changes: 86 additions & 26 deletions easytls-client-disconnect.sh
Original file line number Diff line number Diff line change
Expand Up @@ -383,45 +383,103 @@ disconnect_accepted
# There is only one way out of this...
if [ $absolute_fail -eq 0 ]
then
# Update connection tracking
conntrac_record="${UV_TLSKEY_SERIAL:-TLSAC}"
conntrac_record="${conntrac_record}=${client_serial}=${common_name}"
# shellcheck disable=SC2154
conntrac_record="${conntrac_record}=${ifconfig_pool_remote_ip}"
if [ $ENABLE_CONN_TRAC ]
then
conn_trac_disconnect "${conntrac_record}" "${EASYTLS_CONN_TRAC}" || {
ctd_fail=1
update_status "conn_trac_disconnect FAIL"
[ $FATAL_CONN_TRAC ] && die "CONNTRAC_DISCONNECT_FAIL" 99
}
# Update connection tracking
conntrac_record="${UV_TLSKEY_SERIAL:-TLSAC}"
conntrac_record="${conntrac_record}=${client_serial}"
# If common_name is not set then this is bug 160-2
# Use username, which is still set, when common_name is lost
# Set the username alternative first
# shellcheck disable=SC2154
conntrac_alt_rec="${conntrac_record}=${username}"
conntrac_alt2_rec="${conntrac_record}=${X509_0_CN}"
conntrac_record="${conntrac_record}=${common_name}"

# shellcheck disable=SC2154
conntrac_record="${conntrac_record}=${ifconfig_pool_remote_ip}"
conntrac_alt_rec="${conntrac_alt_rec}=${ifconfig_pool_remote_ip}"
conntrac_alt2_rec="${conntrac_alt2_rec}=${ifconfig_pool_remote_ip}"
# shellcheck disable=SC2154
conntrac_record="${conntrac_record}++${untrusted_ip}:${untrusted_port}"
conntrac_alt_rec="${conntrac_alt_rec}++${untrusted_ip}:${untrusted_port}"
conntrac_alt2_rec="${conntrac_alt2_rec}++${untrusted_ip}:${untrusted_port}"

# Disconnect common_name
conn_trac_disconnect "${conntrac_record}" "${EASYTLS_CONN_TRAC}"
conntrac_errcode=$?

case $conntrac_errcode in
2) update_status "conn_trac_disconnect ERROR"
conntrac_error=1
log_error=1
;;
1)
update_status "conn_trac_disconnect FAIL"
conntrac_fail=1
log_error=1
[ $FATAL_CONN_TRAC ] && die "CONNTRAC_DISCONNECT_FAIL" 99
;;
0) : ;; # OK
*) die "CONNTRAC_CONNECT_FAIL" 98 ;;
esac
unset conntrac_errcode

if [ $conntrac_error ]
then
# Disconnect username
conn_trac_disconnect "${conntrac_alt_rec}" "${EASYTLS_CONN_TRAC}"
conntrac_alt_errcode=$?

case $conntrac_alt_errcode in
2) update_status "conn_trac_disconnect ALT ERROR"
conntrac_alt_error=1
log_error=1
;;
1)
update_status "conn_trac_disconnect ALT FAIL"
conntrac_alt_fail=1
[ $FATAL_CONN_TRAC ] && die "CONNTRAC_DISCONNECT_ALT_FAIL" 99
log_error=1
;;
0) : ;; # OK
*) die "CONNTRAC_CONNECT_ALT_FAIL" 98 ;;
esac
unset conntrac_alt_errcode
fi

# Log failure
if [ $ctd_fail ]
if [ $conntrac_fail ] || [ $conntrac_error ]
then
{
[ -f "${EASYTLS_CONN_TRAC}.fail" ] && \
"${EASYTLS_CAT}" "${EASYTLS_CONN_TRAC}.fail"
"${EASYTLS_PRINTF}" '%s\n' "${conntrac_record}"
"${EASYTLS_PRINTF}" '%s ' "$(date '+%x %X')"
[ $conntrac_fail ] && "${EASYTLS_PRINTF}" '%s ' "FAIL"
[ $conntrac_error ] && "${EASYTLS_PRINTF}" '%s ' "NFound"
"${EASYTLS_PRINTF}" '%s\n' "DIS: ${conntrac_record}"
} > "${EASYTLS_CONN_TRAC}.fail.tmp"
"${EASYTLS_MV}" "${EASYTLS_CONN_TRAC}.fail.tmp" \
"${EASYTLS_CONN_TRAC}.fail"
fi

conntrac_record="${UV_TLSKEY_SERIAL:-TLSAC}"
conntrac_record="${conntrac_record}=${client_serial}=.*"
# shellcheck disable=SC2154
conntrac_record="${conntrac_record}=${ifconfig_pool_remote_ip}"

if grep -q "${conntrac_record}" "${EASYTLS_CONN_TRAC}"
then
sed -i "/${conntrac_record}/d" "${EASYTLS_CONN_TRAC}" || \
die "conntrac sed FAIL"
update_status "conn_trac_disconnect FORCED"
else
# This is bad
update_status "conn_trac_disconnect FORCED FAIL"
fi
if [ $conntrac_alt_fail ] || [ $conntrac_alt_error ]
then
{
[ -f "${EASYTLS_CONN_TRAC}.fail" ] && \
"${EASYTLS_CAT}" "${EASYTLS_CONN_TRAC}.fail"
"${EASYTLS_PRINTF}" '%s ' "$(date '+%x %X')"
[ $conntrac_alt_fail ] && "${EASYTLS_PRINTF}" '%s ' "AFAIL"
[ $conntrac_alt_error ] && "${EASYTLS_PRINTF}" '%s ' "ANFound"
"${EASYTLS_PRINTF}" '%s\n' "DIS: ${conntrac_alt_rec}"
} > "${EASYTLS_CONN_TRAC}.fail.tmp"
"${EASYTLS_MV}" "${EASYTLS_CONN_TRAC}.fail.tmp" \
"${EASYTLS_CONN_TRAC}.fail"
fi

# Capture env
if [ $log_error ]
then
env_file="${temp_stub}-client-disconnect.env"
if [ $EASYTLS_FOR_WINDOWS ]; then
set > "${env_file}"
Expand All @@ -430,6 +488,8 @@ then
fi
unset env_file
fi

[ $conntrac_alt_error ] && die "conntrac_alt_error"
else
update_status "conn-trac disabled"
fi
Expand Down
32 changes: 24 additions & 8 deletions easytls-conntrac.lib
Original file line number Diff line number Diff line change
Expand Up @@ -46,21 +46,29 @@ conn_trac_connect ()
easytls_ct_lock_file="${2}.lock"
easytls_temp_file="${2}.tmp"
acquire_lock || die "ct acquire_lock"
err_exit=0

# Pattern to match
conntrac_pattern="${1}"

if [ -f "${2}" ]
then
{
while read conn
while read full_conn
do
if [ "${conn}" = "${1}" ]
conn="${full_conn}"
if [ "${conn}" = "${conntrac_pattern}" ]
then
# Already exists - Print nothing
already_registered=1
update_status "conntrac: already registered"
[ $VERBOSE_CONN_TRAC ] && update_status "${1}"
else
"${EASYTLS_PRINTF}" '%s\n' "${conn}"
# Print the existing record
"${EASYTLS_PRINTF}" '%s\n' "${full_conn}"
fi
done < "${2}"
# If not already registered then print it
[ $already_registered ] || "${EASYTLS_PRINTF}" "%s\n" "${1}"
} > "${easytls_temp_file}"

Expand All @@ -69,12 +77,13 @@ conn_trac_connect ()

if [ $already_registered ]
then
err_exit=1
err_exit=2
else
update_status "conn-trac: registered"
[ $VERBOSE_CONN_TRAC ] && update_status "${1}"
fi
else
# conntrac file does not exist, create it now
{
"${EASYTLS_PRINTF}" "%s\n" "${1}"
} > "${2}" || err_exit=1
Expand All @@ -94,19 +103,26 @@ conn_trac_disconnect ()
easytls_ct_lock_file="${2}.lock"
easytls_temp_file="${2}.tmp"
acquire_lock || die "ct acquire_lock"
err_exit=0

# Pattern to match
conntrac_pattern="${1%++*}"

if [ -f "${2}" ]
then
{
while read conn
while read full_conn
do
if [ "${conn}" = "${1}" ]
conn="${full_conn%++*}"
if [ "${conn}" = "${conntrac_pattern}" ]
then
# Matched - Do not Print
conntrac_updated=1
update_status "conntrac: unregistered"
[ $VERBOSE_CONN_TRAC ] && update_status "${1}"
else
"${EASYTLS_PRINTF}" '%s\n' "${conn}"
# No match - Print
"${EASYTLS_PRINTF}" '%s\n' "${full_conn}"
fi
done < "${2}"
} > "${easytls_temp_file}"
Expand All @@ -115,7 +131,7 @@ conn_trac_disconnect ()
[ $conntrac_updated ] || {
update_status "conntrac: record not found"
[ $VERBOSE_CONN_TRAC ] && update_status "${1}"
err_exit=1
err_exit=2
}
[ -s "${2}" ] || {
"${EASYTLS_RM}" -f "${2}"
Expand Down

0 comments on commit 9864cfa

Please sign in to comment.