#!/bin/bash # Copyright: 2023 Virtuozzo International GmbH # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # http://www.apache.org/licenses/LICENSE-2.0 # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. DESCRIPTION="Firewall module"; VERSION="1.1"; DEFAULT_ACTION="Usage"; inherit tests os envinfo log net config; include cartridge-common virtuozzo vzexec; $PROGRAM 'iptables' $PROGRAM 'ip6tables' $PROGRAM 'find'; $PROGRAM 'xargs'; $PROGRAM 'netstat'; $PROGRAM 'rpcinfo' $PROGRAM 'ip'; $PROGRAM 'sort'; $PROGRAM 'sed'; $PROGRAM 'grep'; $PROGRAM 'awk'; $PROGRAM 'iptables-restore' $PROGRAM 'iptables-save' $PROGRAM 'ip6tables-restore' $PROGRAM 'ip6tables-save' $PROGRAM 'vzctl' #posible values: iptables, nftables BACKEND='iptables' declare PublicIP; declare FTPPort; declare RSLV_ADDR; declare CORE_ADDR; declare APP_ADDR; declare DB_ADDR; declare -a OPENPORTS; declare -a CLOSEDPORTS; declare -r ERR_NO_METADATA=4080; CTID=0 OS="" OS_ver="" function _getbalancerRedirPorts() { return 0; } function _getapache_phpRedirPorts { return 0; } function _getnginx_phpRedirPorts { return 0; } function _getmavenRedirPorts { return 0; } function _getnginx_rubyRedirPorts { return 0; } function _getcartridgePorts() { #restoreEnvironmentVariables; echo $($SED -re 's/"//g' <<< $($SED -re 's/Private_Port=//g' <<< $(cat $MANIFEST_EXPORTED | $GREP "Private_Port=" ))| sort -u) ${FTPPort}; return 0; } function _getcartridgeRedirPorts () { echo "PREROUTING:0.0.0.0/0:0.0.0.0/0:80:8080:REDIRECT"; return 0; } function _getglassfishRedirPorts () { echo "PREROUTING:0.0.0.0/0:0.0.0.0/0:80:28080:REDIRECT PREROUTING:0.0.0.0/0:0.0.0.0/0:443:8743:REDIRECT OUTPUT:0.0.0.0/0:127.0.0.0/8:80:28080:REDIRECT"; return 0; } function _defaultComputeNodeRedirPorts () { return 0; } function _computeRedirPorts () { echo "PREROUTING:0.0.0.0/0:0.0.0.0/0:80:8080:REDIRECT PREROUTING:0.0.0.0/0:0.0.0.0/0:443:8743:REDIRECT OUTPUT:0.0.0.0/0:127.0.0.0/8:80:8080:REDIRECT"; return 0; } function _getjettyRedirPorts () { echo "PREROUTING:0.0.0.0/0:0.0.0.0/0:80:8080:REDIRECT PREROUTING:0.0.0.0/0:0.0.0.0/0:443:8743:REDIRECT OUTPUT:0.0.0.0/0:127.0.0.0/8:80:8080:REDIRECT"; return 0; } function _getapache_rubyRedirPorts() { return 0; } function _getcouchdbRedirPorts() { return 0; } function _getmysqlRedirPorts() { return 0; } function _getmariadbRedirPorts() { return 0; } function _getmongodbRedirPorts() { return 0; } function _getpostgresRedirPorts() { return 0; } function _isPublicIPv4() { getAddr "venet0" "ipv4" [[ "${#ipv4_list[@]}" -ne 0 ]] && { for ip in ${ipv4_list[@]} ; do [[ "${ip}" == "127.0.0.1" ]] && continue; isLANIP "$ip" || return 0; done; } return 1; } function __getAllIPs() { echo $($IP a l | $SED -rne '/inet/{s/.*inet6.* //;s/\/.*//;s/peer.*//;s/in.*\s+(.*)/\1/; /(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])/p}' | sort -u | $SED -re ':a;N;$!ba;s/\n/ /g;'); } function getLANIPs() { local IPS=$(__getAllIPs); local res=(); for ip in ${IPS[@]} ; do [[ "${ip}" == "127.0.0.1" ]] && continue; isLANIP "${ip}" && res=(${res} ${ip}); done; echo "${res[@]}"; } function isRange() { : ${1:?"Missing param: Port to test"}; $GREP -qP "[-|:]" <<< $1; return $?; } function _setDefaultPolicy() { setDefaultPolicy $1 } function _saveCurrentRules() { saveCurrentRules } function doSave() { _saveCurrentRules 2>>$ACTIONS_LOG && writeJSONResponseOut "result=>0" "message=>Firewall has been saved" || writeJSONResponseErr "result=>4143" "message=>Cannot save configuration files!" } function describeSave() { echo "save firewall rules"; } function doUsage() { showUsageMessage } function onModLoadCallback() { log "Preload callback"; local __closedports __openports ## TODO: remove "params" garbarge option local temp=`getopt -l ctid:,rules: -- params "$@" 2>/dev/null` oldifs; [[ $? != 0 ]] && die -q "Terminating..."; eval set -- "$temp"; while true ; do case "$1" in --ctid) shift CTID=$1 vzexecSetCTID $CTID shift ;; --rules) shift; oldifs=$IFS; IFS=';'; RULES=(${1// /}); IFS=${oldifs}; shift; ;; --) shift; break; ;; esac done local _prefix="" if [[ "$CTID" -gt 0 ]] ; then VZ_CTID_PRIVATE=$(vzlist -Ho private $CTID ) VZ_CTID_ROOT=$(vzlist -Ho root $CTID ) _prefix="/$VZ_CTID_ROOT" fi local issue_file=$_prefix/etc/issue local release_files=$_prefix/etc/*-release local issue_string=$(set +f; cat $release_files $issue_file 2>/dev/null); OS=$(detectOS "$issue_string") OS_ver=$(getOSVersion "$issue_string") OS_ver=${OS_ver%%.*} #do we started "inside" if [[ "$CTID" -eq 0 ]] ; then if [[ "$UID" == '0' ]]; then ACTIONS_LOG="/var/log/actions$$.log"; else ACTIONS_LOG="/tmp/actions$$.log"; fi _isPublicIPv4 && PublicIP=$__TRUE || publicIP=$__FALSE #do not perform any operration if container not started if [ -d /run/systemd/system ] ; then count=10 while [[ $count -gt 0 ]] ; do out=$(systemctl is-system-running) if [[ "x$out" == "xstarting" ]] ; then count=$((count-1)) sleep 1 else count=0 fi echo "`date +%D.%k:%M:%S.%N`: $action:$subaction - waiting start $count" >> $JEM_CALLS_LOG done fi FTPPort=$($NETSTAT -tnlp | $SED -n -re '/ftp/{s/((\S+)\s+){3}(\S+)\s+((\S+)\s+)+/\3/;s/[^:]+:([0-9]+)/\1/;s/://g;p}'); NFSPort=$($RPCINFO -p 127.0.0.1 2>/dev/null | $SED -n -re '/nfs/{s/\s+(\S+\s+)+([0-9]+)\s+nfs.*/\2/g;p}' | uniq | $SED -e ':a' -e 'N' -e '$!ba' -e 's/\n/ /g' | $SED -e 's/ /,/g' ) RPCPort=$($RPCINFO -p 127.0.0.1 2>/dev/null | $SED -n -re '/(portmapper|nlockmgr|mountd)/{s/\s+(\S+\s+)+([0-9]+)\s+.*/\2/g;p}' | uniq | $SED -e ':a' -e 'N' -e '$!ba' -e 's/\n/ /g' | $SED -e 's/ /,/g' ) if [ "x$OS" == "xcentos" -a "$OS_ver" -ge "7" ] ; then IPTABLES="$IPTABLES -w" IP6TABLES="$IP6TABLES -w" IPTABLES_RESTORE="$IPTABLES_RESTORE -w" IP6TABLES_RESTORE="$IP6TABLES_RESTORE -w" fi fi if [ "x$OS" == "xalmalinux" -a "$OS_ver" -ge "9" ] ; then inherit nftables else inherit iptables fi return 0 } function describeStart() { echo "start firewall and load rules"; } function describeStartParameters() { echo "--rules string --ctid integer"; } function describeStartOptions() { echo "rules: firewall rules to apply"; echo "ctid: container id"; } function doStart() { local cartridge_config="/opt/repo/jelastic/jelastic.conf"; [ -f "$cartridge_config" ] && Firewall_Enabled=$($GREP Firewall_Enabled "$cartridge_config" | $AWK -F "=" '{ print $2 }') [ ! -z "${Firewall_Enabled}" ] && FIREWALL_ENABLED=${Firewall_Enabled}; ### Override for cartridges [[ "${FIREWALL_ENABLED}" -eq "0" ]] || [ -z "${FIREWALL_ENABLED+xxx}" ] || [ -z "${FIREWALL_ENABLED}" -a "${FIREWALL_ENABLED+xxx}" = "xxx" ] && return 0; netfilterStart _saveCurrentRules return 0 } function describeFWStart() { echo "Alias for Start"; } function doFWStart() { local resultMsg declare -i result if [[ $CTID -eq 0 ]] ; then log "FWSTART configuring firewall" resultMsg=$(doStart); result=$? else resultMsg=$(vzctl exec2 $CTID "jem firewall start"); result=$? fi [[ "$result" -eq "0" ]] && writeJSONResponseOut "result=>${result}" "message=>Firewall has been started" || writeJSONResponseErr "result=>${result}" "message=>${resultMsg}" return $result } function describeStop() { echo "clear all rules and stop firewall"; } function doStop() { netfilterStop } function describeFWStop() { echo "Alias for Stop"; } function doFWStop() { local resultMsg; declare -i result; resultMsg=$(doStop); result=$?; [[ "${result}" ]] && writeJSONResponseOut "result=>${result}" "message=>Firewall has been stopped" || writeJSONResponseErr "result=>${result}" "message=>${resultMsg}"; } function _isFWEnabled() { local status=$($SED -rne '/FIREWALL_ENABLED/{s/FIREWALL_ENABLED=([0-1]){1}/\1/;p}' ${META_FILE}) local cartridge_config="/opt/repo/jelastic/jelastic.conf" if [ -f "$cartridge_config" ] ; then status=$($GREP Firewall_Enabled "$cartridge_config" | $AWK -F "=" '{ print $2 }') [ -z "${status}" ] && status="1" fi [[ "${status}" -eq "1" ]] && return 0 return 1 } function doisEnabled() { _isFWEnabled } function describeFWStatus() { echo "displays firewall status"; } function doFWStatus() { local param=${1}; [[ -z ${param} ]] && { _isFWEnabled && writeJSONResponseOut "result=>0" "message=>Firewall enabled" || writeJSONResponseOut "result=>0" "message=>Firewall disabled"; return 0; } message=$($IPTABLES -vnL INPUT | $SED -re '/INPUT/d;/target/d;s/\s*((\S+)\s+){8}(\S+)\s+(.*)/\4/g' | $SED -rne '/^\s*$/d;/:/{s/.*dpt(s)?:([0-9]+)(:)?([0-9]+)?.*/\2:\4/;p}' | $SED -re ':a;N;$!ba;s/\n/,/g;s/:,/,/g;s/:$//g'); message="Open ports: ${message}"; writeJSONResponseOut "result=>0" "message=>${message}"; return 0; } function describeFWReconfigure() { echo "reconfigure firewall"; } function describeFWReconfigureParameters() { describeStartParameters } function describeFWReconfigureOptions() { describeStartOptions } function doFWReconfigure() { _isFWEnabled && doStart } function describeEnable() { echo "enable firewall"; } function describeEnableParameters() { describeStartParameters } function describeEnableOptions() { describeStartOptions } function doEnable() { [ ! -e "${META_FILE}" ] && touch ${META_FILE} if $GREP -q "FIREWALL_ENABLED" ${META_FILE} ; then $SED -i -re "s/FIREWALL_ENABLED=([0-9]+)/FIREWALL_ENABLED=1/g" ${META_FILE} else echo -e "\nFIREWALL_ENABLED=1" >> ${META_FILE} $SED -i -re '/^$/d' ${META_FILE} fi netfilterEnable writeJSONResponseOut "result=>0" "message=>Firewall has been enabled" return 0 } function describeFWEnable() { echo "Alias for Enable"; } function doFWEnable() { declare -i result if [[ $CTID -eq 0 ]] ; then local resultMsg resultMsg=$(doEnable); result=$? [[ "${result}" ]] && writeJSONResponseOut "result=>${result}" "message=>Firewall has been enabled" || writeJSONResponseErr "result=>${result}" "message=>${resultMsg}" return $result fi resultMsg=$(vzctl exec2 $CTID "jem firewall Enable"); result=$? if [[ "${result}" -gt 0 ]] ; then writeJSONResponseErr "result=>${result}" "message=>${resultMsg}" return 1 fi FWSetMsg=$(dofwset $@) eval $($SED -re 's/.*"result":"([0-9]+)".*"message":"([^"]+)".*/fwset_result="\1";fwset_msg="\2"/g' <<< $FWSetMsg) [[ "$fwset_result" -gt 0 ]] && writeJSONResponseErr "result=>$fwset_result" "message=>$fwset_msg" writeJSONResponseOut "result=>0" "message=>Firewall has been enabled" return 0 } function describeDisable() { echo "disable firewall"; } function doDisable() { [ ! -e "${META_FILE}" ] && touch ${META_FILE} netfilterStop if $GREP -q "FIREWALL_ENABLED" ${META_FILE} ; then $SED -i -re "s/FIREWALL_ENABLED=([0-9]+)/FIREWALL_ENABLED=0/g" ${META_FILE}; fi _setDefaultPolicy "ACCEPT" _saveCurrentRules writeJSONResponseOut "result=>0" "message=>Firewall has been disabled" return 0; } function describeDisable() { echo "Alias for Disable"; } function doFWDisable() { local resultMsg declare -i result if [[ $CTID -eq 0 ]] ; then resultMsg=$(doDisable); result=$? else resultMsg=$(vzctl exec2 $CTID "jem firewall Disable"); result=$? fi [[ "${result}" ]] && writeJSONResponseOut "result=>${result}" "message=>Firewall has been disabled" || writeJSONResponseErr "result=>${result}" "message=>${resultMsg}" } function describePanic() { echo "clear all rules and set default policy to DROP"; } function doPanic() { netfilterStop _setDefaultPolicy "DROP" _saveCurrentRules return 0 } function doList() { netfilterList $@ } function dofwset() { running=1 if ! isContainerRunning ${CTID} ; then running=0 vzctl mount ${CTID} >> $ACTIONS_LOG 2>&1 fi firewallSet if [[ $running -eq 1 ]] ; then vzexecRun "jem firewall start" else vzctl umount ${CTID} >> $ACTIONS_LOG 2>&1 fi log="$(vzexecGetLastStdOut) $(vzexecGetLastStdErr)" local _errCode=$(vzexecGetLastErrCode) if [[ "$_errCode" -gt 0 ]] ; then writeJSONResponseOut "result=>4068" "message=>Firewall rules are not set properly" "log=>${log//\"/\\\"}" else writeJSONResponseOut "result=>0" "message=>Firewall rules set" "log=>${log//\"/\\\"}" fi return 0 }