Skip to content

Commit afb597e

Browse files
thomassagaborigloi
authored andcommitted
CP-24777: NBD firewalling: interfaces not addresses
Change nbd-firewall-config.sh such that it deals with interfaces (e.g. eth2, lo, xenbr4 etc.) rather than IP addresses. Signed-off-by: Thomas Sanders <[email protected]>
1 parent c222848 commit afb597e

File tree

1 file changed

+64
-47
lines changed

1 file changed

+64
-47
lines changed

scripts/nbd-firewall-config.sh

Lines changed: 64 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -2,82 +2,99 @@
22
#
33
# Copyright (c) Citrix Systems. All rights reserved.
44

5-
set -e
6-
75
##############################################################
86
# Use this script to open/close the specified interfaces
9-
# (IP addresses) for incoming TCP connections to the NBD port.
7+
# for incoming TCP connections to the NBD port.
108
#
119
# Usage:
12-
# ./nbd-firewall-config set [address...]
10+
# ./nbd-firewall-config set [interface...]
1311
#
1412
##############################################################
1513

14+
# Historical note: the original version of this file filtered
15+
# by local IP addresses rather than by network interfaces;
16+
# that version might one day be a useful reference for something.
17+
1618
# Require the "set" argument because otherwise there would be a risk
1719
# of someone running the script with no arguments and accidentally
18-
# setting NBD to be available on no addresses.
20+
# setting NBD to be available on no interfaces.
1921
# This way, omitting "set" (or supplying "--help") causes the script
2022
# to print usage instructions.
2123

24+
set -e
2225
OP="$1"
2326
if [ _"${OP}" != _set ]; then
24-
echo "Usage: $(basename ${0}) set [address...]
27+
echo "Usage: $(basename ${0}) set [interface...]
2528
will set the firewall to allow incoming TCP connections
26-
to the NBD port on only the specified addresses (if any)." 1>&2
29+
to the NBD port on only the specified interfaces (if any)." 1>&2
2730
exit 1
2831
fi
2932
shift 1
3033

3134
set -eu
32-
33-
TMPSET=xapi_nbd_ipset_ephemeral
34-
NBDSET=xapi_nbd_ipset
35+
# No automatic cleanup on error because it would depend too
36+
# critically on the stage at which the error occurs.
37+
38+
# If this script has been run already then there will be existing chains and
39+
# rules in place already. Therefore the approach is:
40+
# 1. Make new nbd-specific chains with names ending in "_new".
41+
# 2. Insert rules into main INPUT/OUTPUT chains to use our new chains.
42+
# 3. Remove preexisting rules that use preexisting nbd chains (if present).
43+
# 4. Remove preexisting nbd chains (if present).
44+
# 5. Rename the new chains so they no longer end in "_new".
45+
46+
# Note that chain names must be under 29 characters.
47+
NewChainIn=xapi_nbd_input_chain_new
48+
NbdChainIn=xapi_nbd_input_chain
49+
NewChainOut=xapi_nbd_output_chain_new
50+
NbdChainOut=xapi_nbd_output_chain
51+
52+
# IANA-assigned port: the NBD protocol specifies that it SHOULD be used.
3553
NBDPORT=10809
36-
SETTYPE=hash:ip
37-
38-
# Rule to accept new NBD connections on the appropriate addresses
39-
NBD_ACCEPT="-p tcp --dport $NBDPORT -m conntrack --ctstate NEW -m set --match-set $NBDSET dst -j ACCEPT"
4054

41-
# Rules to reject NBD packets on disallowed addresses,
42-
# inbound and outbound,
43-
# even if part of an established connection.
44-
NBD_REJECT_IN="-p tcp --dport $NBDPORT -m set ! --match-set $NBDSET dst -j REJECT"
45-
NBD_REJECT_OUT="-p tcp --sport $NBDPORT -m set ! --match-set $NBDSET src -j REJECT"
46-
47-
function destroy_tmp {
48-
ipset destroy $TMPSET 2>/dev/null || true
49-
}
50-
51-
destroy_tmp
52-
trap destroy_tmp ERR EXIT
55+
# Rule fragments for sending NBD packets to NBD chains
56+
# from INPUT and OUTPUT chains.
57+
NBD_INPUT_JUMP_TO="-p tcp --dport $NBDPORT -j "
58+
NBD_OUTPUT_JUMP_TO="-p tcp --sport $NBDPORT -j "
5359

5460
# Same principle as double-buffering a display:
55-
# add the items one by one to a temporary ipset,
56-
# then swap it into use atomically.
57-
ipset create $TMPSET $SETTYPE
58-
61+
# add the items one by one to temporary chains,
62+
# then swap them into use atomically, or as near as possible.
63+
iptables --new-chain $NewChainIn 2>/dev/null || iptables --flush $NewChainIn
64+
iptables --new-chain $NewChainOut 2>/dev/null || iptables --flush $NewChainOut
5965
while [ "$#" -ne 0 ]; do
60-
addr="${1}"
66+
intf="${1}"
67+
# (Each positional param is forgotten for ever at the end of the loop.)
6168
shift 1
62-
ipset add $TMPSET "${addr}"
69+
iptables -A $NewChainIn -m conntrack --ctstate NEW,ESTABLISHED --in-interface "${intf}" -j ACCEPT
70+
iptables -A $NewChainOut --out-interface "${intf}" -j RETURN
6371
done
72+
iptables --append $NewChainIn -j REJECT
73+
iptables --append $NewChainOut -j REJECT
6474

65-
ipset create -exist $NBDSET $SETTYPE
66-
ipset swap $TMPSET $NBDSET
67-
ipset destroy $TMPSET
75+
function insert_rule_if_absent {
76+
chain="${1}"
77+
shift 1
78+
rule="${*}"
79+
iptables --check "${chain}" $rule 2>/dev/null || \
80+
iptables --insert "${chain}" $rule
81+
}
6882

69-
# Now create the rules if they do not exist already.
70-
# Note: the ip set must exist before we can add an iptables rule that uses it.
71-
for rule in "$NBD_ACCEPT" "$NBD_REJECT_IN"; do
72-
if ! iptables --check INPUT $rule 2>/dev/null
73-
then
74-
iptables --insert INPUT $rule
75-
fi
76-
done
83+
# Start using the new chains.
84+
insert_rule_if_absent INPUT "${NBD_INPUT_JUMP_TO} ${NewChainIn}"
85+
insert_rule_if_absent OUTPUT "${NBD_OUTPUT_JUMP_TO} ${NewChainOut}"
7786

78-
if ! iptables --check OUTPUT $NBD_REJECT_OUT 2>/dev/null
79-
then
80-
iptables --insert OUTPUT $NBD_REJECT_OUT
81-
fi
87+
# If old chains are present, stop using them and then delete them.
88+
iptables --delete INPUT $NBD_INPUT_JUMP_TO $NbdChainIn 2>/dev/null || true
89+
iptables --flush "${NbdChainIn}" 2>/dev/null && \
90+
iptables --delete-chain "${NbdChainIn}"
91+
92+
iptables --delete OUTPUT $NBD_OUTPUT_JUMP_TO $NbdChainOut 2>/dev/null || true
93+
iptables --flush "${NbdChainOut}" 2>/dev/null && \
94+
iptables --delete-chain "${NbdChainOut}"
8295

96+
# Rename our rules so they no longer appear new.
97+
# (References remain valid, pointing to the renamed chains.)
98+
iptables --rename-chain "${NewChainIn}" "${NbdChainIn}"
99+
iptables --rename-chain "${NewChainOut}" "${NbdChainOut}"
83100
exit 0

0 commit comments

Comments
 (0)