From 3f5e1b5b601411f5f1309901b1d4c0420d7089af Mon Sep 17 00:00:00 2001 From: Tom Eastep Date: Sat, 22 Feb 2020 10:49:18 -0800 Subject: [PATCH 01/15] Update interface file example in the Introduction article Signed-off-by: Tom Eastep --- docs/Introduction.xml | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/docs/Introduction.xml b/docs/Introduction.xml index 495467fdd..704ba870a 100644 --- a/docs/Introduction.xml +++ b/docs/Introduction.xml @@ -16,7 +16,7 @@ - 2003-2015 + 2003-2020 Thomas M. Eastep @@ -170,17 +170,21 @@ dmz ipv4 file. In the three-interface sample, the three zones are defined using that file as follows: - #ZONE INTERFACE BROADCAST OPTIONS -net eth0 detect dhcp,routefilter -loc eth1 detect -dmz eth2 detect + #ZONE INTERFACE OPTIONS +net NET_IF tcpflags,dhcp,nosmurfs,routefilter,logmartians,sourceroute=0,physical=eth0 +loc LOC_IF tcpflags,nosmurfs,routefilter,logmartians,physical=eth1 +dmz DMZ_IF tcpflags,nosmurfs,routefilter,logmartians,physical=eth2 The above file defines the net zone as all IPv4 hosts interfacing to the firewall through eth0, the loc zone as all IPv4 hosts interfacing through eth1 and the dmz as all IPv4 hosts interfacing through - eth2. It is important to note that the composition of a zone is defined in - terms of a combination of addresses and + eth2. The interface names shown in the INTERFACE column are + logical names which are used throughout the configuration to + refer to the individual interfaces. The actual interface names are + specified using the physical option. It + is important to note that the composition of a zone is defined in terms of + a combination of addresses and interfaces. When using the /etc/shorewall/interfaces file to define a zone, all addresses are included; when you want to define @@ -190,10 +194,12 @@ dmz eth2 detect file or you may use the nets= option in /etc/shorewall/interfaces: - #ZONE INTERFACE BROADCAST OPTIONS -net eth0 detect dhcp,routefilter,nets=(!192.168.0.0/23) -loc eth1 detect nets=(192.168.0.0/24) -dmz eth2 detect nets=(192.168.1.0/24) + #ZONE INTERFACE OPTIONS +net NET_IF tcpflags,dhcp,nosmurfs,routefilter,logmartians,sourceroute=0,physical=eth0 +loc LOC_IF tcpflags,nosmurfs,routefilter,logmartians,physical=eth1,nets=172.20.1.0/24 +dmz DMZ_IF tcpflags,nosmurfs,routefilter,logmartians,physical=eth2 + The above file defines the net zone as all IPv4 hosts interfacing to the firewall through eth0 except From caa74754834a752b98f5569fbb7330807089ff20 Mon Sep 17 00:00:00 2001 From: Tom Eastep Date: Sat, 22 Feb 2020 11:31:19 -0800 Subject: [PATCH 02/15] Accomodate both DOCKER-ISOLATION and DOCKER-ISOLATION-STAGE-* Previously, the code assumed that either DOCKER-ISOLATION or DOCKER-ISOLATION-STAGE-* would exist but not both. That has been corrected --- Shorewall/Perl/Shorewall/Chains.pm | 7 +++++-- Shorewall/Perl/Shorewall/Compiler.pm | 6 +++--- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/Shorewall/Perl/Shorewall/Chains.pm b/Shorewall/Perl/Shorewall/Chains.pm index 4c65f0f8f..df30d8884 100644 --- a/Shorewall/Perl/Shorewall/Chains.pm +++ b/Shorewall/Perl/Shorewall/Chains.pm @@ -8713,6 +8713,9 @@ sub save_docker_rules($) { qq( ;;), qq( Two\)), qq( rm -f \${VARDIR}/.filter_DOCKER-ISOLATION*), + qq( if chain_exists DOCKER_ISOLATION; then), + qq( $tool -t filter -S DOCKER-ISOLATION | tail -n +2 > \${VARDIR}/.filter_DOCKER-ISOLATION), + qq( fi), qq( $tool -t filter -S DOCKER-ISOLATION-STAGE-1 | tail -n +2 > \${VARDIR}/.filter_DOCKER-ISOLATION-STAGE-1), qq( $tool -t filter -S DOCKER-ISOLATION-STAGE-2 | tail -n +2 > \${VARDIR}/.filter_DOCKER-ISOLATION-STAGE-2), qq( ;;), @@ -9238,7 +9241,7 @@ sub create_netfilter_load( $ ) { } elsif ( $name eq 'DOCKER-ISOLATION' ) { ensure_cmd_mode; emit( '[ "$g_dockernetwork" = One ] && echo ":DOCKER-ISOLATION - [0:0]" >&3' ); - } elsif ( $name =~ /^DOCKER-ISOLATION-/ ) { + } elsif ( $name =~ /^DOCKER-ISOLATION/ ) { ensure_cmd_mode; emit( qq([ "\$g_dockernetwork" = Two ] && echo ":$name - [0:0]" >&3) ); } elsif ( $name eq 'DOCKER-INGRESS' ) { @@ -9454,7 +9457,7 @@ sub create_stop_load( $ ) { } elsif ( $name eq 'DOCKER-ISOLATION' ) { ensure_cmd_mode; emit( '[ -n "$g_dockernetwork" ] && echo ":DOCKER-ISOLATION - [0:0]" >&3' ); - } elsif ( $name =~ /^DOCKER-ISOLATION-/ ) { + } elsif ( $name =~ /^DOCKER-ISOLATION/ ) { ensure_cmd_mode; emit( qq([ "\$g_dockernetwork" = Two ] && echo ":$name - [0:0]" >&3) ); } elsif ( $name eq 'DOCKER-INGRESS' ) { diff --git a/Shorewall/Perl/Shorewall/Compiler.pm b/Shorewall/Perl/Shorewall/Compiler.pm index a666af0b0..926326708 100644 --- a/Shorewall/Perl/Shorewall/Compiler.pm +++ b/Shorewall/Perl/Shorewall/Compiler.pm @@ -270,10 +270,10 @@ sub generate_script_2() { ); emit( 'chain_exists DOCKER-INGRESS && g_dockeringress=Yes' ); emit( 'chain_exists DOCKER-USER && g_dockeruser=Yes' ); - emit( 'if chain_exists DOCKER-ISOLATION; then', - ' g_dockernetwork=One', - 'elif chain_exists DOCKER-ISOLATION-STAGE-1; then', + emit( 'if chain_exists DOCKER-ISOLATION-STAGE-1; then', ' g_dockernetwork=Two', + 'elif chain_exists DOCKER-ISOLATION; then', + ' g_dockernetwork=One', 'fi' ); } From 6798c2f2b0f7b821f82553cd88847f3acb9ac7f6 Mon Sep 17 00:00:00 2001 From: Tom Eastep Date: Sat, 22 Feb 2020 11:31:19 -0800 Subject: [PATCH 03/15] Accomodate both DOCKER-ISOLATION and DOCKER-ISOLATION-STAGE-* Previously, the code assumed that either DOCKER-ISOLATION or DOCKER-ISOLATION-STAGE-* would exist but not both. That has been corrected --- Shorewall/Perl/Shorewall/Chains.pm | 47 +++++++++++++--------------- Shorewall/Perl/Shorewall/Compiler.pm | 11 +++---- Shorewall/Perl/Shorewall/Misc.pm | 16 +++------- Shorewall/Perl/prog.footer | 3 +- 4 files changed, 31 insertions(+), 46 deletions(-) diff --git a/Shorewall/Perl/Shorewall/Chains.pm b/Shorewall/Perl/Shorewall/Chains.pm index 4c65f0f8f..404554b45 100644 --- a/Shorewall/Perl/Shorewall/Chains.pm +++ b/Shorewall/Perl/Shorewall/Chains.pm @@ -3369,13 +3369,13 @@ sub initialize_chain_table($) { add_commands( $chainref, '[ -f ${VARDIR}/.nat_DOCKER ] && cat ${VARDIR}/.nat_DOCKER >&3' ); $chainref = new_standard_chain( 'DOCKER-INGRESS' ); set_optflags( $chainref, DONT_OPTIMIZE | DONT_DELETE | DONT_MOVE ); - add_commands( $chainref, '[ -f ${VARDIR}/.filter_DOCKER-INGRESS ] && cat ${VARDIR}/.filter_DOCKER-INGRESS >&3' ); - $chainref = new_standard_chain( 'DOCKER-USER' ); + add_commands( $chainref, '[ -f ${VARDIR}/.filter_DOCKER-INGRESS ] && cat ${VARDIR}/.filter_DOCKER-INGRESS >&3' ); + $chainref = new_standard_chain( 'DOCKER-USER' ); set_optflags( $chainref, DONT_OPTIMIZE | DONT_DELETE | DONT_MOVE ); - add_commands( $chainref, '[ -f ${VARDIR}/.filter_DOCKER-USER ] && cat ${VARDIR}/.filter_DOCKER-USER >&3' ); + add_commands( $chainref, '[ -f ${VARDIR}/.filter_DOCKER-USER ] && cat ${VARDIR}/.filter_DOCKER-USER >&3' ); $chainref = new_standard_chain( 'DOCKER-ISOLATION' ); set_optflags( $chainref, DONT_OPTIMIZE | DONT_DELETE | DONT_MOVE ); - add_commands( $chainref, '[ -f ${VARDIR}/.filter_DOCKER-ISOLATION ] && cat ${VARDIR}/.filter_DOCKER-ISOLATION >&3' ); + add_commands( $chainref, '[ -f ${VARDIR}/.filter_DOCKER-ISOLATION ] && cat ${VARDIR}/.filter_DOCKER-ISOLATION >&3' ); $chainref = new_standard_chain( 'DOCKER-ISOLATION-STAGE-1' ); set_optflags( $chainref, DONT_OPTIMIZE | DONT_DELETE | DONT_MOVE ); add_commands( $chainref, '[ -f ${VARDIR}/.filter_DOCKER-ISOLATION-STAGE-1 ] && cat ${VARDIR}/.filter_DOCKER-ISOLATION-STAGE-1 >&3' ); @@ -8703,20 +8703,15 @@ sub save_docker_rules($) { qq( $tool -t nat -S OUTPUT | tail -n +2 | fgrep DOCKER > \${VARDIR}/.nat_OUTPUT), qq( $tool -t nat -S POSTROUTING | tail -n +2 | fgrep -v SHOREWALL | fgrep -v LIBVIRT > \${VARDIR}/.nat_POSTROUTING), qq( $tool -t filter -S DOCKER | tail -n +2 > \${VARDIR}/.filter_DOCKER), - qq( [ -n "\$g_dockeringress" ] && $tool -t filter -S DOCKER-INGRESS | tail -n +2 > \${VARDIR}/.filter_DOCKER-INGRESS), - qq( [ -n "\$g_dockeruser" ] && $tool -t filter -S DOCKER-USER | tail -n +2 > \${VARDIR}/.filter_DOCKER-USER), + qq( rm -f \${VARDIR}/.filter_DOCKER-*), + qq( [ -n "\$g_dockeringress" ] && $tool -t filter -S DOCKER-INGRESS | tail -n +2 > \${VARDIR}/.filter_DOCKER-INGRESS), + qq( [ -n "\$g_dockeruser" ] && $tool -t filter -S DOCKER-USER | tail -n +2 > \${VARDIR}/.filter_DOCKER-USER), + qq( [ -n "\$g_dockeriso" ] && $tool -t filter -S DOCKER-ISOLATION | tail -n +2 > \${VARDIR}/.filter_DOCKER-ISOLATION), qq(), - qq( case "\$g_dockernetwork" in), - qq( One\)), - qq( rm -f \${VARDIR}/.filter_DOCKER-ISOLATION*), - qq( $tool -t filter -S DOCKER-ISOLATION | tail -n +2 > \${VARDIR}/.filter_DOCKER-ISOLATION), - qq( ;;), - qq( Two\)), - qq( rm -f \${VARDIR}/.filter_DOCKER-ISOLATION*), - qq( $tool -t filter -S DOCKER-ISOLATION-STAGE-1 | tail -n +2 > \${VARDIR}/.filter_DOCKER-ISOLATION-STAGE-1), - qq( $tool -t filter -S DOCKER-ISOLATION-STAGE-2 | tail -n +2 > \${VARDIR}/.filter_DOCKER-ISOLATION-STAGE-2), - qq( ;;), - qq( esac), + qq( if [ -n "\$g_dockerisostage" ]; then), + qq( $tool -t filter -S DOCKER-ISOLATION-STAGE-1 | tail -n +2 > \${VARDIR}/.filter_DOCKER-ISOLATION-STAGE-1), + qq( $tool -t filter -S DOCKER-ISOLATION-STAGE-2 | tail -n +2 > \${VARDIR}/.filter_DOCKER-ISOLATION-STAGE-2), + qq( fi), qq(), ); @@ -9237,10 +9232,10 @@ sub create_netfilter_load( $ ) { emit( '[ -n "$g_docker" ] && echo ":DOCKER - [0:0]" >&3' ); } elsif ( $name eq 'DOCKER-ISOLATION' ) { ensure_cmd_mode; - emit( '[ "$g_dockernetwork" = One ] && echo ":DOCKER-ISOLATION - [0:0]" >&3' ); - } elsif ( $name =~ /^DOCKER-ISOLATION-/ ) { + emit( '[ -n "$g_dockeriso" ] && echo ":DOCKER-ISOLATION - [0:0]" >&3' ); + } elsif ( $name =~ /^DOCKER-ISOLATION/ ) { ensure_cmd_mode; - emit( qq([ "\$g_dockernetwork" = Two ] && echo ":$name - [0:0]" >&3) ); + emit( qq([ "\$g_dockerisostage" = Two ] && echo ":$name - [0:0]" >&3) ); } elsif ( $name eq 'DOCKER-INGRESS' ) { ensure_cmd_mode; emit( '[ -n "$g_dockeringress" ] && echo ":DOCKER-INGRESS - [0:0]" >&3' ); @@ -9352,11 +9347,11 @@ sub preview_netfilter_load() { print "\n"; } elsif ( $name eq 'DOCKER-ISOLATION' ) { ensure_cmd_mode1; - print( '[ "$g_dockernetwork" = One ] && echo ":DOCKER-ISOLATION - [0:0]" >&3' ); + print( '[ -n "$g_dockeriso" ] && echo ":DOCKER-ISOLATION - [0:0]" >&3' ); print "\n"; - } elsif ( $name =~ /^DOCKER-ISOLATION-/ ) { + } elsif ( $name =~ /^DOCKER-ISOLATION/ ) { ensure_cmd_mode1; - print( qq([ "\$g_dockernetwork" = Two ] && echo ":$name - [0:0]" >&3) ); + print( qq([ "\$g_dockeisostage" ] && echo ":$name - [0:0]" >&3) ); print "\n"; } elsif ( $name eq 'DOCKER-INGRESS' ) { ensure_cmd_mode1; @@ -9453,10 +9448,10 @@ sub create_stop_load( $ ) { emit( '[ -n "$g_docker" ] && echo ":DOCKER - [0:0]" >&3' ); } elsif ( $name eq 'DOCKER-ISOLATION' ) { ensure_cmd_mode; - emit( '[ -n "$g_dockernetwork" ] && echo ":DOCKER-ISOLATION - [0:0]" >&3' ); - } elsif ( $name =~ /^DOCKER-ISOLATION-/ ) { + emit( '[ -n "$g_dockeriso" ] && echo ":DOCKER-ISOLATION - [0:0]" >&3' ); + } elsif ( $name =~ /^DOCKER-ISOLATION/ ) { ensure_cmd_mode; - emit( qq([ "\$g_dockernetwork" = Two ] && echo ":$name - [0:0]" >&3) ); + emit( qq([ -n "\$g_dockerisostage" ] && echo ":$name - [0:0]" >&3) ); } elsif ( $name eq 'DOCKER-INGRESS' ) { ensure_cmd_mode; emit( '[ -n "$g_dockeringress" ] && echo ":DOCKER-INGRESS - [0:0]" >&3' ); diff --git a/Shorewall/Perl/Shorewall/Compiler.pm b/Shorewall/Perl/Shorewall/Compiler.pm index a666af0b0..c8977bd4b 100644 --- a/Shorewall/Perl/Shorewall/Compiler.pm +++ b/Shorewall/Perl/Shorewall/Compiler.pm @@ -268,13 +268,10 @@ sub generate_script_2() { emit( '', 'chain_exists DOCKER nat && chain_exists DOCKER && g_docker=Yes', ); - emit( 'chain_exists DOCKER-INGRESS && g_dockeringress=Yes' ); - emit( 'chain_exists DOCKER-USER && g_dockeruser=Yes' ); - emit( 'if chain_exists DOCKER-ISOLATION; then', - ' g_dockernetwork=One', - 'elif chain_exists DOCKER-ISOLATION-STAGE-1; then', - ' g_dockernetwork=Two', - 'fi' ); + emit( 'chain_exists DOCKER-INGRESS && g_dockeringress=Yes' ); + emit( 'chain_exists DOCKER-USER && g_dockeruser=Yes' ); + emit( 'chain_exists DOCKER-ISOLATION && dockeriso=Yes' ); + emit( 'chain_exists DOCKER-ISOLATION-STAGE-1 && dockerisostage=Yes' ); } pop_indent; diff --git a/Shorewall/Perl/Shorewall/Misc.pm b/Shorewall/Perl/Shorewall/Misc.pm index 0ff7fea09..55ed6ba53 100644 --- a/Shorewall/Perl/Shorewall/Misc.pm +++ b/Shorewall/Perl/Shorewall/Misc.pm @@ -679,18 +679,10 @@ sub create_docker_rules() { my $chainref = $filter_table->{FORWARD}; - add_commands( $chainref, '[ -n "$g_dockeringress" ] && echo "-A FORWARD -j DOCKER-INGRESS" >&3', ); - add_commands( $chainref, '[ -n "$g_dockeruser" ] && echo "-A FORWARD -j DOCKER-USER" >&3', ); - add_commands( $chainref , - '', - 'case "$g_dockernetwork" in', - ' One)', - ' echo "-A FORWARD -j DOCKER-ISOLATION" >&3', - ' ;;', - ' Two)', - ' echo "-A FORWARD -j DOCKER-ISOLATION-STAGE-1" >&3', - ' ;;', - 'esac' ); + add_commands( $chainref, '[ -n "$g_dockeringress" ] && echo "-A FORWARD -j DOCKER-INGRESS" >&3' ); + add_commands( $chainref, '[ -n "$g_dockeruser" ] && echo "-A FORWARD -j DOCKER-USER" >&3' ); + add_commands( $chainref, '[ -n "$g_dockeriso" ] && echo "-A FORWARD -j DOCKER-ISOLATION" >&3' ); + add_commands( $chainref, '[ -n "$g_dockerisostage" ] && echo "-A FORWARD -j DOCKER-ISOLATION-STAGE-1" >&3' ); if ( my $dockerref = known_interface('docker0') ) { add_commands( $chainref, 'if [ -n "$g_docker" ]; then' ); diff --git a/Shorewall/Perl/prog.footer b/Shorewall/Perl/prog.footer index f72f648c9..5b5ccba01 100644 --- a/Shorewall/Perl/prog.footer +++ b/Shorewall/Perl/prog.footer @@ -148,7 +148,8 @@ g_compiled= g_file= g_docker= g_dockeringress= -g_dockernetwork= +g_dockeriso= +g_dockerisostage= g_forcereload= g_fallback= From 387b86175966d8c29ed6a4b411a2dcf44a3acd64 Mon Sep 17 00:00:00 2001 From: Tom Eastep Date: Tue, 25 Feb 2020 13:08:58 -0800 Subject: [PATCH 04/15] Correct handling of ORIGDEST with OLD_CONNTRACK_MATCH - Also correct detection of OLD_CONNTRACK_MATCH in shorewall6 Signed-off-by: Tom Eastep --- Shorewall/Perl/Shorewall/Chains.pm | 30 ++++++++++++++++++++++-------- Shorewall/Perl/Shorewall/Config.pm | 6 +++++- 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/Shorewall/Perl/Shorewall/Chains.pm b/Shorewall/Perl/Shorewall/Chains.pm index 404554b45..4ddfcec11 100644 --- a/Shorewall/Perl/Shorewall/Chains.pm +++ b/Shorewall/Perl/Shorewall/Chains.pm @@ -1143,16 +1143,30 @@ sub set_rule_option( $$$ ) { # # Consider each subtype as a separate type # - my ( $invert, $subtype, $val, $rest ) = split ' ', $value; + if ( have_capability( 'OLD_CONNTRACK_MATCH' ) ) { + my ( $subtype, $invert, $val, $rest ) = split ' ', $value; - if ( $invert eq '!' ) { - assert( ! supplied $rest ); - $option = join( ' ', $option, $invert, $subtype ); - $value = $val; + if ( $invert eq '!' ) { + assert( ! supplied $rest ); + $option = join( ' ', $option, $subtype ); + $value = join( ' ', $invert, $val ); + } else { + assert( ! supplied $val ); + $option = join( ' ', $invert , $option ); + $value = $invert; + } } else { - assert( ! supplied $val ); - $option = join( ' ', $option, $invert ); - $value = $subtype; + my ( $invert, $subtype, $val, $rest ) = split ' ', $value; + + if ( $invert eq '!' ) { + assert( ! supplied $rest ); + $option = join( ' ', $option, $invert, $subtype ); + $value = $val; + } else { + assert( ! supplied $val ); + $option = join( ' ', $option, $invert ); + $value = $subtype; + } } $opttype = EXCLUSIVE; diff --git a/Shorewall/Perl/Shorewall/Config.pm b/Shorewall/Perl/Shorewall/Config.pm index 27d1ea4d0..d0b5280b7 100644 --- a/Shorewall/Perl/Shorewall/Config.pm +++ b/Shorewall/Perl/Shorewall/Config.pm @@ -4603,7 +4603,11 @@ sub New_Conntrack_Match() { } sub Old_Conntrack_Match() { - ! qt1( "$iptables $iptablesw -A $sillyname -m conntrack ! --ctorigdst 1.2.3.4" ); + if ( $family == F_IPV4 ) { + ! qt1( "$iptables $iptablesw -A $sillyname -m conntrack ! --ctorigdst 1.2.3.4" ); + } else { + ! qt1( "$iptables $iptablesw -A $sillyname -m conntrack ! --ctorigdst ::1" ); + } } sub Multiport() { From 1ec81b7d7bc24480fb0dc8f7dcfcf9da5d90be6d Mon Sep 17 00:00:00 2001 From: Tom Eastep Date: Wed, 26 Feb 2020 11:39:58 -0800 Subject: [PATCH 05/15] Add correct html.css file to code/docs/ Signed-off-by: Tom Eastep --- docs/html.css | 188 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 188 insertions(+) create mode 100644 docs/html.css diff --git a/docs/html.css b/docs/html.css new file mode 100644 index 000000000..db17dd1f2 --- /dev/null +++ b/docs/html.css @@ -0,0 +1,188 @@ +/* global styles */ +body { + font-family: sans-serif; +} +div { + border: 0; + padding: 0.5em; +} +img { + border: 0; +} +hr { + color: #8b8b8b; +} +h4 { + text-align: center; + font-weight: bold; + padding: 0.25em 0.5em; + margin: 0 0 1px; +} +.quote { + font-style: italic; + text-align: center; +} +.strong { + font-weight: bold; +} +.warning { + font-weight: bold; + color: #ff0000; +} +a { + display: block; + border-width: 0; + text-decoration: none; + color: #0060b5; + background: #ffffff; +} +a:hover { + color: #ffffff; + background: #0060b5; +} +/* header styles */ +div#header { + position: absolute; + font-size: small; + top: 0; + left: 0; + height: 100px; + width: 95%; + margin: 10px; +} +div#header p { + text-align: center; +} +div#header div#search-form { + float: left; + margin: 0; + padding: 0; +} +div#header div#search-form input#search-text { + background-color: #ffffff; + color: #0060b5; + font-size: small; + border: 1px solid; + vertical-align: middle; +} +div#header div#search-form input#submit-button { + background-color: #ffffff; + color: #0060b5; + font-size: small; + font-weight: bold; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + border-radius:6px; + text-decoration: none; + cursor: pointer; + border: 1px solid; + vertical-align: middle; +} +div#header div#search-form input#submit-button:hover { + border: 1px solid; + background-color: #0060b5; + color: #ffffff; + box-shadow: 0px 0px 1px #777; +} +div#header div#ml-search { + float: right; + margin: 0; + padding: 0; +} +div#header div#logo { + margin: 0; + padding: 0; + clear: both; +} +/* sidebar styles */ +div#sidebar { + position: fixed; + top: 125px; + left: 0; + width: 15%; + margin: 10px; + font-size: small; +} +div#sidebar:hover { + background-position: 0px 0px; +} +div#sidebar a { + text-align: center; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + border-radius:6px; +} +/* menu styles */ +/* main panel styles */ +div#main { + position: absolute; + top: 150px; + left: 16%; + width: 62%; + margin: 10px; +} +div#main a { + display: inline; + padding: 0; +} +div#main a:hover { + color: #0060b5; + background: #ffffff; + text-decoration: underline; +} +/* content styles */ +div#content div { + padding: 0; +} +div#content code, pre { + font: 100% monospace; +} +div#content table { + width: 100%; +} +div#content table#changelog { + font-size: x-small; +} +/* footer styles */ +div#footer p { + text-align: center; + font-size: small; +} +div#footer table { + margin-left: auto; + margin-right: auto; +} +/* doc panel styles */ +div#doc { + float: right; + top: 125px; + left: 80%; + width: 15%; + margin: 125px 10px 10px 10px; + font-size: small; +} +div#doc:hover { + background-position: 0px 0px; +} +div#doc a { + padding: 0 5px 0 5px; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + border-radius:6px; +} +div#doc p.go-top, div#doc p.go-top a, div#doc p.go-top a:hover { + opacity: 0.75; + filter:alpha(opacity=75); /* For IE8 and earlier */ + position: fixed; + bottom: 0.5em; + right: 0.5em; + text-decoration: none; + font-size: small; + padding: 0; + display: block; +} +div#doc p.go-top a:hover { + opacity: 1.0; + filter:alpha(opacity=100); /* For IE8 and earlier */ +} + From dcde2bfa4afc046e105542b7d08d9c63fbc4ed7f Mon Sep 17 00:00:00 2001 From: Tom Eastep Date: Wed, 26 Feb 2020 14:39:05 -0800 Subject: [PATCH 06/15] Correct logic that decides if a reload is necessary during enable Signed-off-by: Tom Eastep --- Shorewall/Perl/Shorewall/Providers.pm | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Shorewall/Perl/Shorewall/Providers.pm b/Shorewall/Perl/Shorewall/Providers.pm index d4caf3da9..903abf579 100644 --- a/Shorewall/Perl/Shorewall/Providers.pm +++ b/Shorewall/Perl/Shorewall/Providers.pm @@ -1180,14 +1180,14 @@ CEOF emit "fi\n"; if ( get_interface_option( $interface, 'used_address_variable' ) ) { - my $variable = interface_address( $interface ); + my $variable = get_interface_address( $interface ); - emit( "echo \$$variable > \${VARDIR}/${physical}.address" ); + emit( "echo $variable > \${VARDIR}/${physical}.address" ); } if ( get_interface_option( $interface, 'used_gateway_variable' ) ) { - my $variable = interface_gateway( $interface ); - emit( qq(echo "\$$variable" > \${VARDIR}/${physical}.gateway\n) ); + my $variable = get_interface_gateway( $interface ); + emit( qq(echo "$variable" > \${VARDIR}/${physical}.gateway\n) ); } } else { emit( qq(progress_message "Provider $table ($number) Started") ); @@ -2323,22 +2323,22 @@ sub handle_optional_interfaces() { emit( 'fi' ); if ( get_interface_option( $interface, 'used_address_variable' ) ) { - my $variable = interface_address( $interface ); + my $variable = get_interface_address( $interface ); emit( '', "if [ -f \${VARDIR}/${physical}.address ]; then", - " if [ \$(cat \${VARDIR}/${physical}.address) != \$$variable ]; then", + " if [ \$(cat \${VARDIR}/${physical}.address) != $variable ]; then", ' g_forcereload=Yes', ' fi', 'fi' ); } if ( get_interface_option( $interface, 'used_gateway_variable' ) ) { - my $variable = interface_gateway( $interface ); + my $variable = get_interface_gateway( $interface ); emit( '', "if [ -f \${VARDIR}/${physical}.gateway ]; then", - " if [ \$(cat \${VARDIR}/${physical}.gateway) != \"\$$variable\" ]; then", + " if [ \$(cat \${VARDIR}/${physical}.gateway) != \"$variable\" ]; then", ' g_forcereload=Yes', ' fi', 'fi' ); From 000f120c611a2f00c78d96d26ad17dc7f0a81d72 Mon Sep 17 00:00:00 2001 From: Tom Eastep Date: Sun, 1 Mar 2020 15:07:17 -0800 Subject: [PATCH 07/15] Improve checking when MANGLE_ENABLED=No in shorewall[6].conf - Fatal error when a feature is used that requires the mangle table Signed-off-by: Tom Eastep --- Shorewall/Perl/Shorewall/Config.pm | 25 +++++++++++++++++++------ Shorewall/Perl/Shorewall/Misc.pm | 2 +- Shorewall/Perl/Shorewall/Providers.pm | 4 ++-- Shorewall/Perl/Shorewall/Tc.pm | 2 +- 4 files changed, 23 insertions(+), 10 deletions(-) diff --git a/Shorewall/Perl/Shorewall/Config.pm b/Shorewall/Perl/Shorewall/Config.pm index d0b5280b7..817a7d4ea 100644 --- a/Shorewall/Perl/Shorewall/Config.pm +++ b/Shorewall/Perl/Shorewall/Config.pm @@ -162,6 +162,7 @@ our @EXPORT = qw( have_capability require_capability + require_mangle_capability report_used_capabilities kernel_version @@ -804,7 +805,7 @@ sub add_variables( \% ); # 2. The compiler can run multiple times in the same process so it has to be # able to re-initialize its dependent modules' state. # -sub initialize( $;$$$) { +sub initialize($;$$$) { ( $family, $export, my ( $shorewallrc, $shorewallrc1 ) ) = @_; if ( $family == F_IPV4 ) { @@ -5267,6 +5268,16 @@ sub require_capability( $$$ ) { fatal_error "$description require${singular} $capdesc{$capability} in your kernel and iptables" unless have_capability $capability, 1; } +sub require_mangle_capability( $$$ ) { + my ( $capability, $description, $singular ) = @_; + + if ( $config{MANGLE_ENABLED} ) { + &require_capability( @_ ); + } else { + fatal_error "$description " . ( $singular ? 'is' : 'are' ) . " not available when MANGLE_ENABLED=No in $shorewallrc{product}.conf"; + } +} + # # Return Kernel Version # @@ -6611,6 +6622,7 @@ sub get_configuration( $$$ ) { if ( supplied $config{ACCOUNTING_TABLE} ) { my $value = $config{ACCOUNTING_TABLE}; fatal_error "Invalid ACCOUNTING_TABLE setting ($value)" unless $value eq 'filter' || $value eq 'mangle'; + fatal_error "ACCOUNTING_TABLE=mangle not allowed with MANGLE_ENABLED=No" if $value eq 'mangle' and ! $config{MANGLE_ENABLED}; } else { $config{ACCOUNTING_TABLE} = 'filter'; } @@ -6686,7 +6698,7 @@ sub get_configuration( $$$ ) { $config{IPSET} = '' if supplied $config{IPSET} && $config{IPSET} eq 'ipset'; - require_capability 'MARK' , 'FORWARD_CLEAR_MARK=Yes', 's', if $config{FORWARD_CLEAR_MARK}; + require_mangle_capability 'MARK' , 'FORWARD_CLEAR_MARK=Yes', 's', if $config{FORWARD_CLEAR_MARK}; numeric_option 'TC_BITS' , 8, 0; numeric_option 'MASK_BITS' , 8, 0; @@ -6930,7 +6942,7 @@ sub get_configuration( $$$ ) { if ( $config{TC_ENABLED} ) { fatal_error "TC_ENABLED=$config{TC_ENABLED} is not allowed with MANGLE_ENABLED=No" unless $config{MANGLE_ENABLED}; - require_capability 'MANGLE_ENABLED', "TC_ENABLED=$config{TC_ENABLED}", 's'; + require_mangle_capability 'MANGLE_ENABLED', "TC_ENABLED=$config{TC_ENABLED}", 's'; } if ( supplied( $val = $config{TC_PRIOMAP} ) ) { @@ -7013,9 +7025,10 @@ sub get_configuration( $$$ ) { } require_capability( 'MULTIPORT' , "Shorewall $globals{VERSION}" , 's' ); - require_capability( 'RECENT_MATCH' , 'MACLIST_TTL' , 's' ) if $config{MACLIST_TTL}; - require_capability( 'XCONNMARK' , 'HIGH_ROUTE_MARKS=Yes' , 's' ) if $config{PROVIDER_OFFSET} > 0; - require_capability( 'MANGLE_ENABLED' , 'Traffic Shaping' , 's' ) if $config{TC_ENABLED}; + require_capability( 'RECENT_MATCH' , 'MACLIST_TTL' , 's' ) if $config{MACLIST_TTL}; + + require_mangle_capability( 'XCONNMARK' , 'HIGH_ROUTE_MARKS=Yes' , 's' ) if $config{PROVIDER_OFFSET} > 0; + require_mangle_capability( 'MANGLE_ENABLED' , 'Traffic Shaping' , 's' ) if $config{TC_ENABLED}; if ( $config{WARNOLDCAPVERSION} ) { if ( $capabilities{CAPVERSION} ) { diff --git a/Shorewall/Perl/Shorewall/Misc.pm b/Shorewall/Perl/Shorewall/Misc.pm index 55ed6ba53..7c995cf2e 100644 --- a/Shorewall/Perl/Shorewall/Misc.pm +++ b/Shorewall/Perl/Shorewall/Misc.pm @@ -97,7 +97,7 @@ sub setup_ecn() if ( my $fn = open_file 'ecn' ) { first_entry( sub { progress_message2 "$doing $fn..."; - require_capability 'MANGLE_ENABLED', 'Entries in the ecn file', ''; + require_mangle_capability 'MANGLE_ENABLED', 'Entries in the ecn file', ''; warning_message 'ECN will not be applied to forwarded packets' unless have_capability 'MANGLE_FORWARD'; } ); diff --git a/Shorewall/Perl/Shorewall/Providers.pm b/Shorewall/Perl/Shorewall/Providers.pm index 903abf579..9380e9c8e 100644 --- a/Shorewall/Perl/Shorewall/Providers.pm +++ b/Shorewall/Perl/Shorewall/Providers.pm @@ -594,7 +594,7 @@ sub process_a_provider( $ ) { unless ( $options eq '-' ) { for my $option ( split_list $options, 'option' ) { if ( $option eq 'track' ) { - require_capability( 'MANGLE_ENABLED' , q(The 'track' option) , 's' ); + require_mangle_capability( 'MANGLE_ENABLED' , q(The 'track' option) , 's' ); $track = 1; } elsif ( $option eq 'notrack' ) { $track = 0; @@ -714,7 +714,7 @@ sub process_a_provider( $ ) { $mark = ( $lastmark += ( 1 << $config{PROVIDER_OFFSET} ) ) if $mark eq '-' && $track; if ( $mark ne '-' ) { - require_capability( 'MANGLE_ENABLED' , 'Provider marks' , '' ); + require_mangle_capability( 'MANGLE_ENABLED' , 'Provider marks' , '' ); if ( $tproxy && ! $local ) { $val = $globals{TPROXY_MARK}; diff --git a/Shorewall/Perl/Shorewall/Tc.pm b/Shorewall/Perl/Shorewall/Tc.pm index a0303bf70..53399d1ba 100644 --- a/Shorewall/Perl/Shorewall/Tc.pm +++ b/Shorewall/Perl/Shorewall/Tc.pm @@ -2455,7 +2455,7 @@ sub setup_tc( $ ) { } } } elsif ( -f ( my $fn = find_file( 'tcrules' ) ) ) { - warning_message "The tcrules file is no longer supported -- use '$product update' to convert $fn to an equivalent 'mangle' file"; + warning_message "The tcrules file is no longer supported -- use '$shorewallrc{product} update' to convert $fn to an equivalent 'mangle' file"; } if ( my $fn = open_file( 'mangle', 1, 1 ) ) { From 65e101f30649914cbf38715b86d65afd473acb59 Mon Sep 17 00:00:00 2001 From: Tom Eastep Date: Mon, 2 Mar 2020 08:21:34 -0800 Subject: [PATCH 08/15] Refine handling of MANGLE_ENABLED=No Signed-off-by: Tom Eastep --- Shorewall/Perl/Shorewall/Config.pm | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/Shorewall/Perl/Shorewall/Config.pm b/Shorewall/Perl/Shorewall/Config.pm index 817a7d4ea..80c8a2fcf 100644 --- a/Shorewall/Perl/Shorewall/Config.pm +++ b/Shorewall/Perl/Shorewall/Config.pm @@ -5274,7 +5274,7 @@ sub require_mangle_capability( $$$ ) { if ( $config{MANGLE_ENABLED} ) { &require_capability( @_ ); } else { - fatal_error "$description " . ( $singular ? 'is' : 'are' ) . " not available when MANGLE_ENABLED=No in $shorewallrc{product}.conf"; + fatal_error "$description " . ( $singular ? 'is' : 'are' ) . " not available when MANGLE_ENABLED=No in $shorewallrc{PRODUCT}.conf"; } } @@ -6959,9 +6959,7 @@ sub get_configuration( $$$ ) { } default 'RESTOREFILE' , 'restore'; - default 'DROP_DEFAULT' , 'none'; - default 'REJECT_DEFAULT' , 'none'; default 'BLACKLIST_DEFAULT' , 'none'; default 'QUEUE_DEFAULT' , 'none'; @@ -7026,9 +7024,8 @@ sub get_configuration( $$$ ) { require_capability( 'MULTIPORT' , "Shorewall $globals{VERSION}" , 's' ); require_capability( 'RECENT_MATCH' , 'MACLIST_TTL' , 's' ) if $config{MACLIST_TTL}; - - require_mangle_capability( 'XCONNMARK' , 'HIGH_ROUTE_MARKS=Yes' , 's' ) if $config{PROVIDER_OFFSET} > 0; - require_mangle_capability( 'MANGLE_ENABLED' , 'Traffic Shaping' , 's' ) if $config{TC_ENABLED}; + require_capability( 'XCONNMARK' , 'HIGH_ROUTE_MARKS=Yes' , 's' ) if $config{PROVIDER_OFFSET} > 0; + require_capability( 'MANGLE_ENABLED' , 'Traffic Shaping' , 's' ) if $config{TC_ENABLED}; if ( $config{WARNOLDCAPVERSION} ) { if ( $capabilities{CAPVERSION} ) { From 646f01a3a47ad0d3dc3462a342ecf4512b4b5d9b Mon Sep 17 00:00:00 2001 From: Tom Eastep Date: Mon, 2 Mar 2020 11:05:21 -0800 Subject: [PATCH 09/15] Eliminate spurious 'Resetting...' message from the compiler Signed-off-by: Tom Eastep --- Shorewall/Actions/action.IfEvent | 2 -- 1 file changed, 2 deletions(-) diff --git a/Shorewall/Actions/action.IfEvent b/Shorewall/Actions/action.IfEvent index c7241e2d9..7c93465dc 100644 --- a/Shorewall/Actions/action.IfEvent +++ b/Shorewall/Actions/action.IfEvent @@ -114,8 +114,6 @@ if ( ( $targets{$action} || 0 ) & NATRULE ) { if ( $command & $RESET_CMD ) { require_capability 'MARK_ANYWHERE', '"reset"', 's'; - - print "Resetting....\n"; my $mark = $globals{EVENT_MARK}; # From f63f0bb2f19659d9ae57b2af3f670017077a13fa Mon Sep 17 00:00:00 2001 From: Tom Eastep Date: Tue, 3 Mar 2020 14:38:36 -0800 Subject: [PATCH 10/15] Correct DOCKER code Signed-off-by: Tom Eastep --- Shorewall/Perl/Shorewall/Chains.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Shorewall/Perl/Shorewall/Chains.pm b/Shorewall/Perl/Shorewall/Chains.pm index 4ddfcec11..a9fa504ed 100644 --- a/Shorewall/Perl/Shorewall/Chains.pm +++ b/Shorewall/Perl/Shorewall/Chains.pm @@ -9249,7 +9249,7 @@ sub create_netfilter_load( $ ) { emit( '[ -n "$g_dockeriso" ] && echo ":DOCKER-ISOLATION - [0:0]" >&3' ); } elsif ( $name =~ /^DOCKER-ISOLATION/ ) { ensure_cmd_mode; - emit( qq([ "\$g_dockerisostage" = Two ] && echo ":$name - [0:0]" >&3) ); + emit( qq([ -n "\$g_dockerisostage" ] && echo ":$name - [0:0]" >&3) ); } elsif ( $name eq 'DOCKER-INGRESS' ) { ensure_cmd_mode; emit( '[ -n "$g_dockeringress" ] && echo ":DOCKER-INGRESS - [0:0]" >&3' ); From 9f3534dc1f6b11450b15683d9f750572c14e0f1b Mon Sep 17 00:00:00 2001 From: Tom Eastep Date: Wed, 4 Mar 2020 14:55:52 -0800 Subject: [PATCH 11/15] Correct Docker-related typos in Compiler.pm Signed-off-by: Tom Eastep --- Shorewall/Perl/Shorewall/Compiler.pm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Shorewall/Perl/Shorewall/Compiler.pm b/Shorewall/Perl/Shorewall/Compiler.pm index c8977bd4b..b0c079d27 100644 --- a/Shorewall/Perl/Shorewall/Compiler.pm +++ b/Shorewall/Perl/Shorewall/Compiler.pm @@ -270,8 +270,8 @@ sub generate_script_2() { ); emit( 'chain_exists DOCKER-INGRESS && g_dockeringress=Yes' ); emit( 'chain_exists DOCKER-USER && g_dockeruser=Yes' ); - emit( 'chain_exists DOCKER-ISOLATION && dockeriso=Yes' ); - emit( 'chain_exists DOCKER-ISOLATION-STAGE-1 && dockerisostage=Yes' ); + emit( 'chain_exists DOCKER-ISOLATION && g_dockeriso=Yes' ); + emit( 'chain_exists DOCKER-ISOLATION-STAGE-1 && g_dockerisostage=Yes' ); } pop_indent; From a345be20fb900947493b79dc627aceb67cbda7dc Mon Sep 17 00:00:00 2001 From: Tom Eastep Date: Thu, 5 Mar 2020 15:32:03 -0800 Subject: [PATCH 12/15] Add Cliff Armstrong's workaround to the Docker document Signed-off-by: Tom Eastep --- docs/Docker.xml | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/docs/Docker.xml b/docs/Docker.xml index 92150c98e..02b9bd186 100644 --- a/docs/Docker.xml +++ b/docs/Docker.xml @@ -13,6 +13,10 @@ Eastep + + + J Cliff Armstrong + @@ -20,6 +24,8 @@ 2016 + 2020 + Thomas M. Eastep @@ -57,6 +63,35 @@ restart or reload operation and restores those rules along with the Shorewall-generated ruleset. + + Shorewall currently doesn't support Docker Swarm mode. + + + + On Debian and Debian-derived systems, systemctl restart + shorewall will lose Docker rules. You can work around this + issue using a method provided by J Cliff Armstrong: + + Type as root: + + systemctl edit shorewall.service + + This will open the default terminal editor to a blank file in + which you can paste the following: + + [Service] +# reset ExecStop +ExecStop= +# set ExecStop to "stop" instead of "clear" +ExecStop=/sbin/shorewall $OPTIONS stop + + + Then type systemctl daemon-reload to activate + the changes. This change will survive future updates of the shorewall + package from apt repositories. The override file itself will be saved to + `/etc/systemd/system/shorewall.service.d/`. + + This support assumes that the default Docker bridge (docker0) is being used. It is recommended that this bridge be defined to Shorewall in Date: Fri, 6 Mar 2020 12:33:39 +0100 Subject: [PATCH 13/15] Accommodate for tracking empty target files Signed-off-by: Matt Darfeuille Signed-off-by: Tom Eastep --- .gitignore | 1 - 1 file changed, 1 deletion(-) delete mode 100644 .gitignore diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 6977c13d4..000000000 --- a/.gitignore +++ /dev/null @@ -1 +0,0 @@ -*targetname From 95d34867887dddfd96fd103ac6e29b14e9fd38cd Mon Sep 17 00:00:00 2001 From: Tom Eastep Date: Fri, 6 Mar 2020 09:19:25 -0800 Subject: [PATCH 14/15] Add empty target files 5.2.3.7 Signed-off-by: Tom Eastep --- Shorewall-core/Shorewall-core-targetname | 1 + Shorewall-lite/Shorewall-lite-targetname | 1 + Shorewall/Shorewall-targetname | 1 + Shorewall6-lite/Shorewall6-lite-targetname | 1 + Shorewall6/Shorewall6-targetname | 1 + docs/docs-targetname | 1 + docs/images/docs-images-targetname | 1 + 7 files changed, 7 insertions(+) create mode 100644 Shorewall-core/Shorewall-core-targetname create mode 100644 Shorewall-lite/Shorewall-lite-targetname create mode 100644 Shorewall/Shorewall-targetname create mode 100644 Shorewall6-lite/Shorewall6-lite-targetname create mode 100644 Shorewall6/Shorewall6-targetname create mode 100644 docs/docs-targetname create mode 100644 docs/images/docs-images-targetname diff --git a/Shorewall-core/Shorewall-core-targetname b/Shorewall-core/Shorewall-core-targetname new file mode 100644 index 000000000..a29e62721 --- /dev/null +++ b/Shorewall-core/Shorewall-core-targetname @@ -0,0 +1 @@ +5.2.3.7 \ No newline at end of file diff --git a/Shorewall-lite/Shorewall-lite-targetname b/Shorewall-lite/Shorewall-lite-targetname new file mode 100644 index 000000000..a29e62721 --- /dev/null +++ b/Shorewall-lite/Shorewall-lite-targetname @@ -0,0 +1 @@ +5.2.3.7 \ No newline at end of file diff --git a/Shorewall/Shorewall-targetname b/Shorewall/Shorewall-targetname new file mode 100644 index 000000000..a29e62721 --- /dev/null +++ b/Shorewall/Shorewall-targetname @@ -0,0 +1 @@ +5.2.3.7 \ No newline at end of file diff --git a/Shorewall6-lite/Shorewall6-lite-targetname b/Shorewall6-lite/Shorewall6-lite-targetname new file mode 100644 index 000000000..a29e62721 --- /dev/null +++ b/Shorewall6-lite/Shorewall6-lite-targetname @@ -0,0 +1 @@ +5.2.3.7 \ No newline at end of file diff --git a/Shorewall6/Shorewall6-targetname b/Shorewall6/Shorewall6-targetname new file mode 100644 index 000000000..a29e62721 --- /dev/null +++ b/Shorewall6/Shorewall6-targetname @@ -0,0 +1 @@ +5.2.3.7 \ No newline at end of file diff --git a/docs/docs-targetname b/docs/docs-targetname new file mode 100644 index 000000000..a29e62721 --- /dev/null +++ b/docs/docs-targetname @@ -0,0 +1 @@ +5.2.3.7 \ No newline at end of file diff --git a/docs/images/docs-images-targetname b/docs/images/docs-images-targetname new file mode 100644 index 000000000..a29e62721 --- /dev/null +++ b/docs/images/docs-images-targetname @@ -0,0 +1 @@ +5.2.3.7 \ No newline at end of file From 3e2d7cf99087bcf7f3cce5c3d9098724ac983131 Mon Sep 17 00:00:00 2001 From: Tom Eastep Date: Fri, 6 Mar 2020 09:37:41 -0800 Subject: [PATCH 15/15] Add another targetname file Signed-off-by: Tom Eastep --- Shorewall6-lite/Shorewall-lite6-lite-targetname | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 Shorewall6-lite/Shorewall-lite6-lite-targetname diff --git a/Shorewall6-lite/Shorewall-lite6-lite-targetname b/Shorewall6-lite/Shorewall-lite6-lite-targetname new file mode 100644 index 000000000..e69de29bb