1#!/bin/sh 2# 3# Copyright (C) 2015 Red Hat, Inc. 4# Copyright (C) 2016 Lance LeFlore 5# 6# This file is part of ocserv. 7# 8# This file is free software; you can redistribute it and/or modify it 9# under the terms of the GNU General Public License as published by 10# the Free Software Foundation; either version 2 of the License, or 11# (at your option) any later version. 12# 13# This file is distributed in the hope that it will be useful, but 14# WITHOUT ANY WARRANTY; without even the implied warranty of 15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16# General Public License for more details. 17# 18# You should have received a copy of the GNU General Public License 19# along with this file; if not, write to the Free Software Foundation, 20# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 21 22# Input is from environment: 23# 24# OCSERV_RESTRICT_TO_ROUTES: If set to '1' the user should be restricted 25# to accessing the OCSERV_ROUTES and prevented from accessing 26# OCSERV_NO_ROUTES. 27# 28# OCSERV_ROUTES: A space separated list of IPv4 and IPv6 routes to 29# which the user has access. If empty or not set the 30# user has default route. 31# 32# OCSERV_ROUTES4: A version of OCSERV_ROUTES with IPv4 addresses only. 33# OCSERV_ROUTES6: A version of OCSERV_ROUTES with IPv6 addresses only. 34# 35# OCSERV_NO_ROUTES: A space separated list of IPv4 and IPv6 routes to 36# which the user has NO access. 37# 38# OCSERV_NO_ROUTES4: A version of OCSERV_NO_ROUTES with IPv4 addresses only. 39# OCSERV_NO_ROUTES6: A version of OCSERV_NO_ROUTES with IPv6 addresses only. 40# 41# OCSERV_DNS: A space-separated list of DNS servers the user has access to. 42# OCSERV_DNS4: A version of OCSERV_DNS with IPv4 addresses only. 43# OCSERV_DNS6: A version of OCSERV_DNS with IPv6 addresses only. 44# 45# OCSERV_DENY_PORTS: A space-separated list of port types and ports that the user 46# should be denied access to. An example of the format is: 47# "tcp 443 udp 312 sctp 999 icmp all esp all icmpv6 all" 48# 49# OCSERV_ALLOW_PORTS: A space-separated list of port types and ports that the user 50# should be granted access to. If set the user must be denied access 51# to any other ports. An example of the format is: 52# "tcp 443 udp 312 sctp 999 icmp all esp all icmpv6 all" 53 54PATH=/sbin:/usr/sbin:$PATH 55 56COMMENT="ocserv-fw" 57FORWARD_CHAIN="FORWARD" 58SEC_FORWARD_CHAIN="FORWARD-${COMMENT}-${DEVICE}" 59 60if test "$1" = "--removeall";then 61 eval "$(iptables -S | grep "comment ${COMMENT}" | sed -e 's/-A/-D/g' -e 's/^-/iptables -/g')" 62 eval "$(ip6tables -S | grep "comment ${COMMENT}" | sed -e 's/-A/-D/g' -e 's/^-/ip6tables -/g')" 63 64 #delete chains 65 eval "$(iptables -S | grep "INPUT-${COMMENT}" | sed -e 's/-N/-X/g' -e 's/^-/iptables -/g')" 66 eval "$(ip6tables -S | grep "INPUT-${COMMENT}" | sed -e 's/-N/-X/g' -e 's/^-/ip6tables -/g')" 67 exit 0 68fi 69 70execute_next_script() { 71 if test -n "${OCSERV_NEXT_SCRIPT}";then 72 TMP_SCRIPT="${OCSERV_NEXT_SCRIPT}" 73 unset OCSERV_NEXT_SCRIPT 74 /bin/sh "${TMP_SCRIPT}" 75 fi 76} 77 78clean_all_rules() { 79 eval "$(iptables -S | grep "comment ${COMMENT}" | grep -e "-[io] ${DEVICE}" | sed -e 's/-A/-D/g' -e 's/^-/iptables -/g')" 2>/dev/null 80 eval "$(ip6tables -S | grep "comment ${COMMENT}" | grep -e "-[io] ${DEVICE}" | sed -e 's/-A/-D/g' -e 's/^-/ip6tables -/g')" 2>/dev/null 81 iptables -X ${SEC_FORWARD_CHAIN} 2>/dev/null 82 ip6tables -X ${SEC_FORWARD_CHAIN} 2>/dev/null 83} 84 85if test "${REASON}" = "connect";then 86 #clear any leftover rules for this device 87 clean_all_rules 88 # assume FORWARD policy is REJECT - allow return traffic 89 # may also need to turn kernel knob to allow forwarding 90 iptables -I ${FORWARD_CHAIN} \ 91 -o ${DEVICE} \ 92 -m conntrack --ctstate RELATED,ESTABLISHED \ 93 -j ACCEPT -m comment --comment "${COMMENT}" 94 else 95 if test "${REASON}" = "disconnect";then 96 clean_all_rules 97 set -e 98 execute_next_script 99 exit 0 100 else 101 logger -t ocserv-fw "unknown reason ${REASON}" 102 exit 1 103 fi 104fi 105 106set -e 107 108allow_dns() { 109 "$1" -A ${FORWARD_CHAIN} -i ${DEVICE} -p udp -d "$2" --dport 53 -j ACCEPT --match comment --comment "${COMMENT}" 110 111 "$1" -A ${FORWARD_CHAIN} -i ${DEVICE} -p tcp -d "$2" --dport 53 -m state --state NEW,ESTABLISHED -j ACCEPT --match comment --comment "${COMMENT}" 112} 113 114allow_dns4() { 115 allow_dns iptables "$1" 116} 117 118allow_dns6() { 119 allow_dns ip6tables "$1" 120} 121 122allow_route() { 123 "$1" -A ${SEC_FORWARD_CHAIN} -i ${DEVICE} -d "$2" -j ACCEPT --match comment --comment "${COMMENT}" 124} 125 126allow_route4() { 127 allow_route iptables "$1" 128} 129 130allow_route6() { 131 allow_route ip6tables "$1" 132} 133 134disallow_route() { 135 "$1" -A ${SEC_FORWARD_CHAIN} -i ${DEVICE} -d "$2" -j REJECT --match comment --comment "${COMMENT}" 136} 137 138disallow_route4() { 139 disallow_route iptables "$1" 140} 141 142disallow_route6() { 143 disallow_route ip6tables "$1" 144} 145 146disallow_all() { 147 iptables -A ${FORWARD_CHAIN} -i ${DEVICE} -j REJECT --match comment --comment "${COMMENT}" 148 ip6tables -A ${FORWARD_CHAIN} -i ${DEVICE} -j REJECT --match comment --comment "${COMMENT}" 149} 150 151allow_all() { 152 iptables -A ${FORWARD_CHAIN} -i ${DEVICE} -j ACCEPT --match comment --comment "${COMMENT}" 153 ip6tables -A ${FORWARD_CHAIN} -i ${DEVICE} -j ACCEPT --match comment --comment "${COMMENT}" 154} 155 156allow_port() { 157 proto=$1 158 port=$2 159 160 case "$proto" in 161 icmp) 162 iptables -A FORWARD -i ${DEVICE} -p $proto -j ${SEC_FORWARD_CHAIN} --match comment --comment "${COMMENT}" 163 ;; 164 icmpv6) 165 ip6tables -A FORWARD -i ${DEVICE} -p $proto -j ${SEC_FORWARD_CHAIN} --match comment --comment "${COMMENT}" 166 ;; 167 *) 168 iptables -A FORWARD -i ${DEVICE} -p $proto --dport $port -j ${SEC_FORWARD_CHAIN} --match comment --comment "${COMMENT}" 169 ip6tables -A FORWARD -i ${DEVICE} -p $proto --dport $port -j ${SEC_FORWARD_CHAIN} --match comment --comment "${COMMENT}" 170 ;; 171 esac 172} 173 174deny_port() { 175 proto=$1 176 port=$2 177 178 case "$proto" in 179 icmp) 180 iptables -A ${FORWARD_CHAIN} -i ${DEVICE} -p $proto -j REJECT --match comment --comment "${COMMENT}" 181 ;; 182 icmpv6) 183 ip6tables -A ${FORWARD_CHAIN} -i ${DEVICE} -p $proto -j REJECT --match comment --comment "${COMMENT}" 184 ;; 185 *) 186 iptables -A ${FORWARD_CHAIN} -i ${DEVICE} -p $proto --dport $port -j REJECT --match comment --comment "${COMMENT}" 187 ip6tables -A ${FORWARD_CHAIN} -i ${DEVICE} -p $proto --dport $port -j REJECT --match comment --comment "${COMMENT}" 188 ;; 189 esac 190} 191 192disallow_all_ports() { 193 iptables -A FORWARD -i ${DEVICE} -j REJECT --match comment --comment "${COMMENT}" 194 ip6tables -A FORWARD -i ${DEVICE} -j REJECT --match comment --comment "${COMMENT}" 195} 196 197# Allow DNS lookups 198for i in $OCSERV_DNS4;do 199 allow_dns4 $i 200done 201 202# block or allow routes 203for i in $OCSERV_DNS6;do 204 allow_dns6 $i 205done 206 207# create the chain 208FORWARD_CHAIN="${SEC_FORWARD_CHAIN}" 209iptables -N "${FORWARD_CHAIN}" 210ip6tables -N "${FORWARD_CHAIN}" 211 212# block ports - if needed 213if test -n "${OCSERV_DENY_PORTS}";then 214 set ${OCSERV_DENY_PORTS} 215 while test $# -gt 1; do 216 proto=$1 217 port=$2 218 219 deny_port $proto $port 220 if test $# -gt 1;then 221 shift 2 222 else 223 break 224 fi 225 done 226else 227 if test -n "${OCSERV_ALLOW_PORTS}";then 228 set ${OCSERV_ALLOW_PORTS} 229 while test $# -gt 1; do 230 proto=$1 231 port=$2 232 233 allow_port $proto $port 234 if test $# -gt 1;then 235 shift 2 236 else 237 break 238 fi 239 done 240 disallow_all_ports 241 fi 242fi 243 244if test "${OCSERV_RESTRICT_TO_ROUTES}" = "1";then 245 for i in $OCSERV_NO_ROUTES4;do 246 disallow_route4 $i 247 done 248 249 for i in $OCSERV_NO_ROUTES6;do 250 disallow_route6 $i 251 done 252 253 if test -n "$OCSERV_ROUTES";then 254 255 for i in $OCSERV_ROUTES4;do 256 allow_route4 $i 257 done 258 259 for i in $OCSERV_ROUTES6;do 260 allow_route6 $i 261 done 262 263 # no default route, don't allow anything except the configured routes 264 disallow_all 265 else 266 allow_all 267 fi 268else 269 # we still need to allow traffic through if OCSERV_RESTRICT_TO_ROUTES is not true 270 iptables -A ${SEC_FORWARD_CHAIN} -i ${DEVICE} -j ACCEPT -m comment --comment "${COMMENT}" 271fi 272 273# send traffic to the route chain 274iptables -A FORWARD -i ${DEVICE} -j ${SEC_FORWARD_CHAIN} --match comment --comment "${COMMENT}" 275ip6tables -A FORWARD -i ${DEVICE} -j ${SEC_FORWARD_CHAIN} --match comment --comment "${COMMENT}" 276 277execute_next_script 278 279exit 0 280