From f77b2394376aa4c531c856ce302bcb4ec0c3c898 Mon Sep 17 00:00:00 2001 From: Michael Gmelin Date: Tue, 19 Dec 2023 19:12:46 +0100 Subject: [PATCH] New global config to isolate vnet pots This new global setting called `POT_ISOLATE_VNET_POTS` sets bridge member epaira interfaces to be private, preventing them from forwarding traffic to each other. This helps with overall security, but (primarily) makes sure that pots in larger nomad clusters don't talk to each other using direct communication instead of published (natted) endpoints. This could be a more fine-grained per pot setting in the future, in our setups we only ever needed a global setting decided by the infrastructure operator (so, e.g., in the nomad cluster, everything uses this setting, whereas in the more static part forming the infrastructure the nomad cluster relies on, direct communication between pots is wanted) and changing it per pot would be a disadvantage - hence this implementation. --- CHANGELOG.md | 1 + etc/pot/pot.conf.sample | 3 +++ etc/pot/pot.default.conf | 4 ++++ share/pot/common.sh | 18 ++++++++++++++++++ share/pot/set-attribute.sh | 18 ------------------ share/pot/start.sh | 31 ++++++++++++++++++++++++------- 6 files changed, 50 insertions(+), 25 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2477836..29a3251 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Added - tinirc: Write tinirc's pid to /tmp/tinirc.pid (#277) - set-attr/stop: Add attributes exec_stop and stop_timeout (#275) +- vnet: Add global configuration POT_ISOLATE_VNET_POTS to prevent direct traffic between VNET pots (#XXX) ### Fixed - tinirc: Overwrite tinirc on start instead of appending to an existing file (#277) diff --git a/etc/pot/pot.conf.sample b/etc/pot/pot.conf.sample index 4dec3b6..510b10c 100644 --- a/etc/pot/pot.conf.sample +++ b/etc/pot/pot.conf.sample @@ -43,6 +43,9 @@ # POT_NETWORK_vlan20=192.168.100.0/24 # POT_NETWORK_vlan50=10.50.50.0/24 +# Do not allow bridge-based pots to forward traffic to each other +# POT_ISOLATE_VNET_POTS=true + # DNS on the Internal Virtual Network # name of the pot running the DNS diff --git a/etc/pot/pot.default.conf b/etc/pot/pot.default.conf index 8e53528..769ab20 100644 --- a/etc/pot/pot.default.conf +++ b/etc/pot/pot.default.conf @@ -46,6 +46,10 @@ POT_DNS_NAME=dns # IP of the DNS POT_DNS_IP=10.192.0.2 +# If set to true, isolate pot vnet bridge members +# (by using `ifconfig private `, see ifconfig(8)) +POT_ISOLATE_VNET_POTS=false + # If not empty, this script will be called by pot and the pf rules # returned on stdout will be loaded into "pot-rdr/anchor" instead # of those which pot would usually create. This also skips diff --git a/share/pot/common.sh b/share/pot/common.sh index 0748578..a3e8fcb 100644 --- a/share/pot/common.sh +++ b/share/pot/common.sh @@ -182,6 +182,24 @@ _get_system_uptime() { sysctl -n kern.boottime | sed -e 's/.*[^u]sec = \([0-9]*\).*$/\1/' } +# check if the argument is a valid boolean value +# if valid, it returns true and it echo a normalized version of the boolean value (YES/NO) +# if not valid, it return false +_normalize_true_false() { + case $1 in + [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]) + echo YES + return 0 # true + ;; + [Nn][Oo]|[Ff][Aa][Ll][Ss][Ee]|[Oo][Ff][Ff]) + echo NO + return 0 # true + ;; + *) + return 1 # false + esac +} + # validate some values of the configuration files # $1 quiet / no _error messages are emitted _conf_check() diff --git a/share/pot/set-attribute.sh b/share/pot/set-attribute.sh index 65973fc..6d276f4 100644 --- a/share/pot/set-attribute.sh +++ b/share/pot/set-attribute.sh @@ -16,24 +16,6 @@ set-attribute-help() EOH } -# check if the argument is a valid boolean value -# if valid, it returns true and it echo a normalized version of the boolean value (YES/NO) -# if not valid, it return false -_normalize_true_false() { - case $1 in - [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]) - echo YES - return 0 # true - ;; - [Nn][Oo]|[Ff][Aa][Ll][Ss][Ee]|[Oo][Ff][Ff]) - echo NO - return 0 # true - ;; - *) - return 1 # false - esac -} - # $1 pot name # $2 attribute name # $3 value diff --git a/share/pot/start.sh b/share/pot/start.sh index 056b475..159fb87 100644 --- a/share/pot/start.sh +++ b/share/pot/start.sh @@ -172,7 +172,7 @@ _js_create_epair() # $3 epairb interface _js_vnet() { - local _pname _bridge _epaira _epairb _ip + local _pname _bridge _epaira _epairb _ip _param _pname=$1 if ! _is_vnet_ipv4_up ; then _info "Internal network not found! Calling vnet-start to fix the issue" @@ -182,9 +182,14 @@ _js_vnet() _epaira=$2 _epairb=$3 ifconfig "$_epaira" up - ifconfig "$_bridge" addm "$_epaira" + _param=$(_save_params "addm" "$_epaira") + if [ "$(_normalize_true_false "$POT_ISOLATE_VNET_POTS")" = "YES" ]; then + _param="$_param"$(_save_params "private" "$_epaira") + fi + eval "set -- $_param" + ifconfig "$_bridge" "$@" _ip=$( _get_ip_var "$_pname" ) - ## if norcscript - write a ad-hoc one + ## if norcscript - write an ad-hoc one if [ "$(_get_conf_var "$_pname" "pot.attr.no-rc-script")" = "YES" ]; then cat >>"${POT_FS_ROOT}/jails/$_pname/m/tmp/tinirc" <<-EOT if ! ifconfig ${_epairb} >/dev/null 2>&1; then @@ -213,7 +218,7 @@ _js_vnet() # $4 stack (ipv6 or dual) _js_vnet_ipv6() { - local _pname _bridge _epaira _epairb _ip + local _pname _bridge _epaira _epairb _ip _param _pname=$1 if ! _is_vnet_ipv6_up ; then _info "Internal network not found! Calling vnet-start to fix the issue" @@ -223,7 +228,12 @@ _js_vnet_ipv6() _epaira=$2 _epairb=$3 ifconfig "$_epaira" up - ifconfig "$_bridge" addm "$_epaira" + _param=$(_save_params "addm" "$_epaira") + if [ "$(_normalize_true_false "$POT_ISOLATE_VNET_POTS")" = "YES" ]; then + _param="$_param"$(_save_params "private" "$_epaira") + fi + eval "set -- $_param" + ifconfig "$_bridge" "$@" if [ "$(_get_conf_var "$_pname" "pot.attr.no-rc-script")" = "YES" ]; then cat >>"${POT_FS_ROOT}/jails/$_pname/m/tmp/tinirc" <<-EOT if ! ifconfig ${_epairb} >/dev/null 2>&1; then @@ -253,7 +263,8 @@ _js_vnet_ipv6() # $3 epairb interface _js_private_vnet() { - local _pname _bridge_name _bridge _epaira _epairb _ip _net_size _gateway + local _pname _bridge_name _bridge _epaira _epairb _ip _net_size + local _gateway _param _pname=$1 _bridge_name="$( _get_conf_var "$_pname" bridge )" if ! _is_vnet_ipv4_up "$_bridge_name" ; then @@ -264,12 +275,18 @@ _js_private_vnet() _epaira=$2 _epairb=$3 ifconfig "$_epaira" up + _param=$(_save_params "addm" "$_epaira") + if [ "$(_normalize_true_false "$POT_ISOLATE_VNET_POTS")" = "YES" ]; then + _param="$_param"$(_save_params "private" "$_epaira") + fi + eval "set -- $_param" + ifconfig "$_bridge" "$@" ifconfig "$_bridge" addm "$_epaira" _ip=$( _get_ip_var "$_pname" ) _net_size="$(_get_bridge_var "$_bridge_name" net)" _net_size="${_net_size##*/}" _gateway="$(_get_bridge_var "$_bridge_name" gateway)" - ## if norcscript - write a ad-hoc one + ## if norcscript - write an ad-hoc one if [ "$(_get_conf_var "$_pname" "pot.attr.no-rc-script")" = "YES" ]; then cat >>"${POT_FS_ROOT}/jails/$_pname/m/tmp/tinirc" <<-EOT if ! ifconfig ${_epairb} >/dev/null 2>&1; then