Giter VIP home page Giter VIP logo

Comments (7)

beppler avatar beppler commented on July 20, 2024 1

Here is it (with some comments

@def $EXT_DEV = ens256;
@def $BKP_DEV = ens224;

domain (ip ip6) {
    table nat {
        # preserve docker rules
        chain (DOCKER DOCKER-INGRESS PREROUTING OUTPUT POSTROUTING) @preserve;
    }

    table filter {
        # preserve docker rules
        chain (DOCKER DOCKER-INGRESS DOCKER-ISOLATION-STAGE-1 DOCKER-ISOLATION-STAGE-2 FORWARD) @preserve;

        chain INPUT {
            policy DROP;

            # connection tracking
            mod state state INVALID DROP;
            mod state state (ESTABLISHED RELATED) ACCEPT;

            # allow local packet
            interface lo ACCEPT;

            # respond to ping
            proto icmp ACCEPT;

            interface $EXT_DEV {
                # allow SSH connections
                saddr 172.30.0.0/17 proto tcp dport ssh ACCEPT;

                # allow HTTP/HTTPS connections
                proto tcp dport (http https) ACCEPT;
            }

            # allow SMTP connections (from docker0 ip range)
            saddr 172.16.0.0/12 proto tcp dport (smtp submission) ACCEPT;

            # allow Data Protector connections
            interface $BKP_DEV saddr 192.168.172.100 proto tcp dport (ssh omni) ACCEPT;
        }

        chain OUTPUT {
            policy ACCEPT;

            # connection tracking
            mod state state INVALID DROP;
            mod state state (ESTABLISHED RELATED) ACCEPT;
        }

        # docker user container rules
        # use @preserve to avoid error on flush
        chain DOCKER-USER @preserve; 
        chain DOCKER-USER {
            # connection tracking
            mod state state INVALID DROP;
            mod state state (ESTABLISHED RELATED) ACCEPT;

            # block external -> container access
            DROP;
        }
    }

    # clear DOCKER-USER to avoid duplicated rules because of @preserve
    @hook pre "iptables -F DOCKER-USER; ip6tables -F DOCKER-USER";
    # remove the original return created by docker (preserved by @preserve)
    @hook post "iptables -D DOCKER-USER -j RETURN; ip6tables -D DOCKER-USER -j RETURN";
    # restore original DOCKER-USER rules after flush 
    @hook flush "iptables -F DOCKER-USER; ip6tables -F DOCKER-USER; iptables -A DOCKER-USER -j RETURN; ip6tables -A DOCKER-USER -j RETURN";
}

from ferm.

powerman avatar powerman commented on July 20, 2024 1

I've managed to configure ferm to keep docker rules even in case we need to have custom rules in other docker-modified chain than filter/FORWARD (in which we already have DOCKER-USER chain out of box).

Here is example for having own rules both in filter/FORWARD and nat/POSTROUTING.

# Docker support.
# To remove docker support later:
# - remove rules under this comment
# - move rules from filter/DOCKER-USER to filter/FORWARD, if any
# - move rules from all other {table}/{chain}-DOCKER-USER to {table}/{chain}, if any
table nat chain (PREROUTING OUTPUT POSTROUTING DOCKER) @preserve;
table filter chain (FORWARD DOCKER DOCKER-ISOLATION-STAGE-1 DOCKER-ISOLATION-STAGE-2) @preserve;
table nat chain (PREROUTING-DOCKER-USER OUTPUT-DOCKER-USER POSTROUTING-DOCKER-USER) {}
@hook post "iptables -t nat -C PREROUTING  -j PREROUTING-DOCKER-USER  2>/dev/null || iptables -t nat -A PREROUTING  -j PREROUTING-DOCKER-USER";
@hook post "iptables -t nat -C OUTPUT      -j OUTPUT-DOCKER-USER      2>/dev/null || iptables -t nat -A OUTPUT      -j OUTPUT-DOCKER-USER";
@hook post "iptables -t nat -C POSTROUTING -j POSTROUTING-DOCKER-USER 2>/dev/null || iptables -t nat -A POSTROUTING -j POSTROUTING-DOCKER-USER";

table nat chain POSTROUTING-DOCKER-USER {
    # our custom rules for nat/POSTROUTING goes here, e.g.:
    outerface eth0 MASQUERADE;
}
table filter chain DOCKER-USER {
    # our custom rules for filter/FORWARD goes here, e.g.:
    protocol tcp dport 25 REJECT reject-with icmp-port-unreachable;
}

@MaxKellermann It may worth to add this example to ferm docs, because using it together with docker is a common enough case (docker is everywhere nowadays) and also is a pain.

Related moby/moby#40544

from ferm.

MaxKellermann avatar MaxKellermann commented on July 20, 2024

Use @preserve (the manual has a section about it).

from ferm.

beppler avatar beppler commented on July 20, 2024

Ok, I tried to use preserve, but the rules are created after that jump RETURN created by docker.

This is the result of iptables -S just after docker is started.

-P INPUT ACCEPT
-P FORWARD DROP
-P OUTPUT ACCEPT
-N DOCKER
-N DOCKER-INGRESS
-N DOCKER-ISOLATION-STAGE-1
-N DOCKER-ISOLATION-STAGE-2
-N DOCKER-USER
-A FORWARD -j DOCKER-USER
-A FORWARD -j DOCKER-ISOLATION-STAGE-1
-A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -o docker0 -j DOCKER
-A FORWARD -i docker0 ! -o docker0 -j ACCEPT
-A FORWARD -i docker0 -o docker0 -j ACCEPT
-A DOCKER-ISOLATION-STAGE-1 -i docker0 ! -o docker0 -j DOCKER-ISOLATION-STAGE-2
-A DOCKER-ISOLATION-STAGE-1 -j RETURN
-A DOCKER-ISOLATION-STAGE-2 -o docker0 -j DROP
-A DOCKER-ISOLATION-STAGE-2 -j RETURN
-A DOCKER-USER -j RETURN

And my configuration file.

@def $EXT_DEV = ens256;
@def $BKP_DEV = ens224;

domain (ip ip6) {
    table nat {
        # preserve docker rules
        chain (DOCKER DOCKER-INGRESS PREROUTING OUTPUT POSTROUTING) @preserve;
    }

    table filter {
        # preserve docker rules
        chain (DOCKER DOCKER-INGRESS DOCKER-ISOLATION-STAGE-1 DOCKER-ISOLATION-STAGE-2 FORWARD) @preserve;

        chain INPUT {
            policy DROP;

            # connection tracking
            mod state state INVALID DROP;
            mod state state (ESTABLISHED RELATED) ACCEPT;

            # allow local packet
            interface lo ACCEPT;

            # respond to ping
            proto icmp ACCEPT;

            interface $EXT_DEV {
                # allow SSH connections
                saddr 172.30.0.0/17 proto tcp dport ssh ACCEPT;

                # allow SMTP connections
                proto tcp dport (smtp submission) ACCEPT;

                # allow HTTP/HTTPS connections
                proto tcp dport (http https) ACCEPT;
            }

            # allow Data Protector connections
            interface $BKP_DEV saddr 192.168.172.100 proto tcp dport (ssh omni) ACCEPT;
        }

        chain OUTPUT {
            policy ACCEPT;

            # connection tracking
            mod state state INVALID DROP;
            mod state state (ESTABLISHED RELATED) ACCEPT;
        }

        # docker user container rules
        chain DOCKER-USER @preserve;
        chain DOCKER-USER {
            # connection tracking
            mod state state INVALID DROP;
            mod state state (ESTABLISHED RELATED) ACCEPT;

            # allow HTTP/HTTPS connections
            proto tcp dport (http https) ACCEPT;
        }
    }
}

The result iptables -S is:

-P INPUT DROP
-P FORWARD DROP
-P OUTPUT ACCEPT
-N DOCKER
-N DOCKER-INGRESS
-N DOCKER-ISOLATION-STAGE-1
-N DOCKER-ISOLATION-STAGE-2
-N DOCKER-USER
-A INPUT -m state --state INVALID -j DROP
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -s 172.30.0.0/17 -i ens256 -p tcp -m tcp --dport 22 -j ACCEPT
-A INPUT -i ens256 -p tcp -m tcp --dport 25 -j ACCEPT
-A INPUT -i ens256 -p tcp -m tcp --dport 587 -j ACCEPT
-A INPUT -i ens256 -p tcp -m tcp --dport 80 -j ACCEPT
-A INPUT -i ens256 -p tcp -m tcp --dport 443 -j ACCEPT
-A INPUT -s 192.168.172.100/32 -i ens224 -p tcp -m tcp --dport 22 -j ACCEPT
-A INPUT -s 192.168.172.100/32 -i ens224 -p tcp -m tcp --dport 5555 -j ACCEPT
-A FORWARD -j DOCKER-USER
-A FORWARD -j DOCKER-ISOLATION-STAGE-1
-A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -o docker0 -j DOCKER
-A FORWARD -i docker0 ! -o docker0 -j ACCEPT
-A FORWARD -i docker0 -o docker0 -j ACCEPT
-A OUTPUT -m state --state INVALID -j DROP
-A OUTPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A DOCKER-ISOLATION-STAGE-1 -i docker0 ! -o docker0 -j DOCKER-ISOLATION-STAGE-2
-A DOCKER-ISOLATION-STAGE-1 -j RETURN
-A DOCKER-ISOLATION-STAGE-2 -o docker0 -j DROP
-A DOCKER-ISOLATION-STAGE-2 -j RETURN
-A DOCKER-USER -j RETURN
-A DOCKER-USER -m state --state INVALID -j DROP
-A DOCKER-USER -m state --state RELATED,ESTABLISHED -j ACCEPT
-A DOCKER-USER -p tcp -m tcp --dport 80 -j ACCEPT
-A DOCKER-USER -p tcp -m tcp --dport 443 -j ACCEPT

Not that ferm rules are created after the original -A DOCKER-USER -j RETURN.

And when I reload ferm rules all the configuration made on DOCKER-USER is duplicated.

That is why I stopped to use @preserve.

But when I stopped it there where an error when I try to flush the rules because of -A FORWARD -j DOCKER-USER rule created by docker.

from ferm.

beppler avatar beppler commented on July 20, 2024

I made it work adding the following hooks in addition to @preserve.

@hook pre "iptables -F DOCKER-USER; ip6tables -F DOCKER-USER";
@hook post "iptables -D DOCKER-USER -j RETURN; ip6tables -D DOCKER-USER -j RETURN";
@hook flush "iptables -F DOCKER-USER; ip6tables -F DOCKER-USER; iptables -A DOCKER-USER -j RETURN; ip6tables -A DOCKER-USER -j RETURN";

from ferm.

nlvw avatar nlvw commented on July 20, 2024

@beppler any chance you could post your complete config? I'm struggling with a similar issue.

from ferm.

 avatar commented on July 20, 2024

@beppler thanks for your config, it helped me quite a lot

My only issue left is when reloading ferm with systemctl reload ferm, my rules in the DOCKER-USER chain are duplicated. When performing a restart, the duplicates are removed correctly.

Since you mentioned this behavior in a previous comment regarding the use of @preserve I'm wondering if there's an error in my config or the issue still persists.

from ferm.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.