Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sync fb_iptables with upstream #257

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions cookbooks/fb_iptables/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,19 +121,19 @@ translated to key-value pairs in the config file. The keys will automatically be
upper-cased and prefixed with `IPTABLES_` or `IP6TABLES_` as necessary. For
example:

```
```ruby
node.default['fb_iptables']['sysconfig']['modules'] = 'nat'
```

would translate to:

```
```bash
IPTABLES_MODULES="nat"
```

and:

```
```bash
IP6TABLES_MODULES="nat"
```

Expand All @@ -144,4 +144,7 @@ if you need to trigger on rules reloading.
### Unsupported features
The `nat` and `security` tables are not currently supported.

However, you can call `FB::Iptables.enable_nat(node)` to safely initialize
the `nat` structures for use.

User defined table are not supported.
144 changes: 144 additions & 0 deletions cookbooks/fb_iptables/files/default/fb_iptables_reload.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
#!/bin/bash
# shellcheck disable=SC2086,SC2018,SC2019,SC1090,SC2064,SC2124,SC2181,SC2002,SC2153,SC2046,SC2173,SC2230
#
# Copyright (c) 2016-present, Facebook, Inc.
# All rights reserved.
#
# 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.
#

# Simple script for chef to call to
# dump and reload custom chain rules

set -u

CONFIG='/etc/fb_iptables.conf'
TMPDIR=$(mktemp -d /tmp/fb_iptables.XXXXXXXXXXXX)
trap "rm -rf $TMPDIR &>/dev/null" exit INT TERM KILL

help_print() {
echo "$0 [4|6] <action>"
exit;
}

exit_error() {
msg="$@"
echo "ERROR: $msg"
exit 1
}

# Walk dynamic changes for a table and dump them to temp files in, if they exist
dump_dynamic_chains() {
local table="$1"
local dynamic_chains="$2"
local outfile
local chain_regex
echo -n " - Stashing dynamic chains on $table: "
for chain in $dynamic_chains; do
echo -n "$chain "
"${IPTABLES_CMD}" -t "$table" -S | grep -q "\-N $chain"
if [ $? -ne 0 ]; then
echo '(no chain yet, nothing to stash) '
continue
fi
outfile=$TMPDIR/${table}_${chain}_rules
chain_regex="\-A $chain "
out=$("${IPTABLES_CMD}" -t "$table" -S)
if [ $? -ne 0 ]; then
exit_error "Failed to stash $chain on $table"
fi
if [ -n "$out" ]; then
echo "$out" | grep "$chain_regex" > "$outfile"
fi
done
echo 'done.'
}

# Restore any registered chains we found and backed up
restore_dynamic_chains() {
local table="$1"
local dynamic_chains="$2"

echo -n " - Restoring dynamic chains on $table: "
for chain in $dynamic_chains; do
echo -n "$chain "
local rules_file=$TMPDIR/${table}_${chain}_rules
if [ ! -r $rules_file ]; then
echo '(no chain to restore) '
continue
fi

${IPTABLES_CMD} -t $table -F $chain
while read -r rule
do
${IPTABLES_CMD} -t $table $rule
done < "$rules_file"
done
echo 'done.'
}

reload_static_chains() {
local table="$1"

# NOTE: You cannot use '-t' here ... ip6tables-* choke on it... you must
# specify --table=
echo " - Reloading $table"
cat "${CONFIG_DIR}/${IPTABLES_RULES_FILE}" | ${IPTABLES_CMD}-restore --table=$table
}

reload() {
for table in $TABLES; do
# iptables-restore triggers loading modules, even with empty
# rules. Let's avoid that (t28313270).
echo "Reloading $table..."
cap_table=$(echo $table | tr 'a-z' 'A-Z')
static_chains=$(eval echo \$STATIC_${cap_table}_CHAINS)
if [ -z "$static_chains" ] && ! grep -q $table /proc/net/ip*_tables_names; then
continue
fi
dynamic_chains=$(eval echo \$${cap_table}_CHAINS)
dump_dynamic_chains $table "$dynamic_chains"
reload_static_chains $table
restore_dynamic_chains $table "$dynamic_chains"
done
}

[ -r "$CONFIG" ] && . $CONFIG

# Poor mans help print
if [ "$1" == "help" ]; then
help_print
fi

# v4 or v6
IPTABLES_CMD=ip6tables
IPTABLES_RULES_FILE="$RULES6_FILE"
if [ "$1" == "4" ]; then
IPTABLES_CMD=iptables
IPTABLES_RULES_FILE="$RULES_FILE"
fi
ACTION="$2"

if [ ! -x $(which "${IPTABLES_CMD}") ]; then
echo "ERROR: No ${IPTABLES_CMD} in path bro ..."
exit 1
fi

case "$ACTION" in
reload)
reload
;;
*)
help_print
;;
esac
32 changes: 31 additions & 1 deletion cookbooks/fb_iptables/libraries/default.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,44 @@ module Iptables
TABLES_AND_CHAINS = {
'mangle' => %w{PREROUTING INPUT OUTPUT FORWARD POSTROUTING},
'filter' => %w{INPUT OUTPUT FORWARD},
'raw' => %w{PREROUTING OUTPUT},
'raw' => %w{PREROUTING OUTPUT},
}
# rubocop:enable Style/MutableConstant

# Facebook, like others does not have NAT in their kernels. However many
# people do, so provide an easy way to initialize the various structures
# with NAT entries.
#
# Note this is idempotent - you can call it many times, it will not
# overwrite user rules
def self.enable_nat(node)
TABLES_AND_CHAINS['nat'] ||= %w{PREROUTING INPUT OUTPUT POSTROUTING}

# normally this would be auto-vivified, but since we want to check
# fb_iptables.nat.$chain below, this has to exist
unless node['fb_iptables']['nat']
node.default['fb_iptables']['nat'] = {}
end

TABLES_AND_CHAINS['nat'].each do |chain|
next if node['fb_iptables']['nat'][chain]

node.default['fb_iptables']['nat'][chain] = {
'policy' => 'ACCEPT',
'rules' => {},
}
end

unless node['fb_iptables']['dynamic_chains']['nat']
node.default['fb_iptables']['dynamic_chains']['nat'] = {}
end
end

# Is the given rule valid for the give ip version
def self.rule_supports_ip_version?(rule, version)
return true unless rule['ip']
return true if rule['ip'] == version

rule['ip'].is_a?(Array) && rule['ip'].include?(version)
end

Expand Down
1 change: 0 additions & 1 deletion cookbooks/fb_iptables/metadata.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
license 'Apache-2.0'
description 'Installs/Configures iptables'
source_url 'https://github.com/facebook/chef-cookbooks/'
long_description IO.read(File.join(File.dirname(__FILE__), 'README.md'))
version '0.1.0'
supports 'centos'
depends 'fb_helpers'
27 changes: 10 additions & 17 deletions cookbooks/fb_iptables/recipes/default.rb
Original file line number Diff line number Diff line change
Expand Up @@ -77,18 +77,19 @@
owner 'root'
group 'root'
mode '0644'
variables(
:iptables_config_dir => iptables_config_dir,
:iptables_rules_file => iptables_rule_file,
:ip6tables_rules_file => ip6tables_rule_file,
)
end

template '/usr/sbin/fb_iptables_reload' do
source 'fb_iptables_reload.erb'
# DO NOT MAKE THIS A TEMPLATE! USE THE CONFIG FILE TEMPLATED ABOVE!!
cookbook_file '/usr/sbin/fb_iptables_reload' do
source 'fb_iptables_reload.sh'
owner 'root'
group 'root'
mode '0755'
variables(
:iptables_config_dir => iptables_config_dir,
:iptables_rules => iptables_rule_file,
:ip6tables_rules => ip6tables_rule_file,
)
end

template "#{iptables_config_dir}/iptables-config" do
Expand All @@ -112,11 +113,7 @@
# moving from "no rules" to any rules; otherwise we still verify
# every time).
if FB::Iptables.iptables_active?(4)
Mixlib::ShellOut.new(
# SCALE: backported
# https://github.com/facebook/chef-cookbooks/pull/56
"/sbin/iptables-restore --test #{path}",
).run_command.exitstatus.zero?
shell_out("/sbin/iptables-restore --test #{path}").exitstatus.zero?
else
true
end
Expand All @@ -141,11 +138,7 @@
verify do |path|
# See comment ip iptables_rules
if FB::Iptables.iptables_active?(6)
Mixlib::ShellOut.new(
# SCALE: backported
# https://github.com/facebook/chef-cookbooks/pull/56
"/sbin/ip6tables-restore --test #{path}",
).run_command.exitstatus.zero?
shell_out("/sbin/ip6tables-restore --test #{path}").exitstatus.zero?
else
true
end
Expand Down
10 changes: 6 additions & 4 deletions cookbooks/fb_iptables/recipes/packages.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,12 @@
# limitations under the License.
#

packages = ['iptables']
if node.centos6?
packages << 'iptables-ipv6'
elsif node.ubuntu?
if (node.centos? && !(node.centos7? || node.centos8?)) || node.fedora?
packages = ['iptables-legacy']
else
packages = ['iptables']
end
if node.ubuntu?
packages << 'iptables-persistent'
else
packages << 'iptables-services'
Expand Down
Loading