kaysond / trafficjam

A Docker firewall for your reverse proxy network
134 stars 8 forks source link

Nextcloud, its database and redis to communicate on selected ports everything else is blocked? #14

Closed mannp closed 5 months ago

mannp commented 2 years ago

Hi there

Thanks for creating this :)

Not sure if the whitelist function is used for this or whether this is a supported config, but how would I config for multiple grouped dockers e.g., Nextcloud, its database and redis, on the same external network behind traefik2?

Application1, its db and redis talk amoungst themselves on selected ports only

   -> App1 is blocked from App2 or App3

Application2, its db and redis talk amoungst themselves on selected ports only

   -> App2 is blocked from App1 or App3

Application3, its db and redis talk amoungst themselves on selected ports only

   -> App3 is blocked from App1 or App2
kaysond commented 2 years ago

That's a very restrictive and complex ruleset that trafficjam just isn't built to support. You could do it manually by forcing docker network parameters (subnet and container IPs) and adding raw iptables rules, but I'd advise against it since it would be prone to errors.

Do you have to have everything on a single network? Best practice in your case anyways would be a separate, dedicated network for each app (e.g. app1_net app2_net app3_net) for intra-app communication, then another network to connect all the app containers (no redis/db) to traefik (e.g. traefik_net). Then you'd run trafficjam on traefik_net to prevent apps from communicating.

In general there shouldn't be a need to make firewall rules port specific because each container should only be running a single service and exposing the relevant ports. Any other requests just won't receive a response.

mrpops2ko commented 5 months ago

i just wanted to bring up a scenario i had and a silly solution, in case others stumble upon this and also want to repeat it because they for some reason need it

so scenario: you have an exposed web application and you also need to direct db expose

if you use trafficjam then you can only expose one through traefik because if you expose the other it will mean the container is in the same network as traefik too and thus the db / app can't communicate with each other (because of the trafficjam rules)

so a solution i had was to just use multiple instances with multiple tags, something like this

  trafficjam:
    container_name: trafficjam
    image: kaysond/trafficjam
    cap_add:
      - NET_ADMIN
    network_mode: host
    volumes:
     - /var/run/docker.sock:/var/run/docker.sock
    depends_on:
      - traefik-reverse-proxy
    environment:
      NETWORK: a-traefik-public
      WHITELIST_FILTER: "label=BYPASS"
      TZ: Europe/London
      INSTANCE_ID: ONE

  jamstraffic:
    container_name: jamstraffic
    image: kaysond/trafficjam
    cap_add:
      - NET_ADMIN
    network_mode: host
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    depends_on:
      - traefik-reverse-proxy
    environment:
      NETWORK: a-traefik-public2
      WHITELIST_FILTER: "label=BYPASS2"
      TZ: Europe/London
      INSTANCE_ID: TWO      

and then you just expose each to different networks and you can continue as you were - it does mean that then your applications need 2 networks but if you create 2 separate external networks like this it means that you won't ever have to restart traefik and can just continue to use labels

i've still not found a way to get SSO to work in the container apps when authing against another internal app [authentik ]but i don't think you can if it resides on the traefik public network as that is by design

kaysond commented 5 months ago

so a solution i had was to just use multiple instances with multiple tags, something like this

Thanks for posting this example! This is indeed the intended usage for such as scenario.

i've still not found a way to get SSO to work in the container apps when authing against another internal app [authentik ]but i don't think you can if it resides on the traefik public network as that is by design

You're right that this is by design. What you could do is have a separate authentik network with all of the containers that need direct authentik access for SSO, then use trafficjam on that network with only authentik whitelisted to prevent the "client" containers from communicating.

Your example and the authentik problem make me think trafficjam might need to support multiple networks natively...

mrpops2ko commented 5 months ago

You're right that this is by design. What you could do is have a separate authentik network with all of the containers that need direct authentik access for SSO, then use trafficjam on that network with only authentik whitelisted to prevent the "client" containers from communicating.

can you flesh this thought out some more? because i also had the same thought and i ended up arriving at it not being possible

so we have traefik, authentik and SSO app (in my case it was vikunja)

traefik sits on networks a-traefik-public a-traefik-public2 with labels bypass and bypass 2

authentik sits on networks a-traefik-public a-traefik-public2 with labels bypass and bypass 2

vikunja sits on a-traefik-public

authentik has SSO as the auth provider

vikunja has native SSO implementation that can auth with authentik [as in, theres a button that you can press on the vikunja app, which will allow them SSO]

now the issue is routing, in that whole scenario vikunja has to make an outgoing connection to authentik and thats the bit we've purposefully blocked in the routing

PING authentik (172.19.0.7): 56 data bytes
^C
--- authentik ping statistics ---
9 packets transmitted, 0 packets received, 100% packet loss

am i doing something wrong here? or is my logic wrong somewhere?

the only way i can think to make it work is via throwing the app on a bypass label or unique network, but in both of those scenarios then we've just returned back to square 1, into a world without trafficjam

as another example

traefik > vikunja

/ # ping vikunja
PING vikunja (172.19.0.9): 56 data bytes
64 bytes from 172.19.0.9: seq=0 ttl=64 time=0.047 ms
64 bytes from 172.19.0.9: seq=1 ttl=64 time=0.043 ms
64 bytes from 172.19.0.9: seq=2 ttl=64 time=0.069 ms
64 bytes from 172.19.0.9: seq=3 ttl=64 time=0.054 ms
64 bytes from 172.19.0.9: seq=4 ttl=64 time=0.045 ms
64 bytes from 172.19.0.9: seq=5 ttl=64 time=0.043 ms
64 bytes from 172.19.0.9: seq=6 ttl=64 time=0.081 ms
64 bytes from 172.19.0.9: seq=7 ttl=64 time=0.052 ms
64 bytes from 172.19.0.9: seq=8 ttl=64 time=0.043 ms
^C
--- vikunja ping statistics ---
9 packets transmitted, 9 packets received, 0% packet loss
round-trip min/avg/max = 0.043/0.053/0.081 ms

vikunja > traefik

/app/vikunja # ping traefik-reverse-proxy
PING traefik-reverse-proxy (172.19.0.3): 56 data bytes
^C
--- traefik-reverse-proxy ping statistics ---
21 packets transmitted, 0 packets received, 100% packet loss
mrpops2ko commented 5 months ago

oh i think i get what your suggesting or at least one way to do it with your suggestion, but it would involve making a new unique network for every app which needs SSO

what you'd do is have say

authentik app sit in authentik-nw-1 to authentik-nw-10

basically make a unique network for each SSO app that needs it

then the app can send an outbound request to authentik and complete SSO

but this means littering my docker networks even more lol, but its the only way i can see to do it natively within the current ruleset

theres nothng we can do with traefik, not that i can see at least - that was my second though on this, that we'd just do some reverse proxy routing but vikunja has to initiate which is the problem

kaysond commented 5 months ago

We're getting a bit beyond the scope of this particular github issue, so I'll leave it at this, but feel free to open a separate issue for more discussion.

The idea is that for everything that traefik is reverse-proxying, you would put all that on a traefik-public network, with trafficjam whitelisting only traefik. For anything that needs internal access to your authentication backend, like traefik forward auth using authentik, you would create an authentik-public network, and only whitelist the authentik container. So anything that goes through traefik is on traefik-public, and anything that uses authentik internally is on authentik-public.

For something like OIDC, you do not need, and in fact you probably don't want, to use the internal connection over the docker network. You need to use the publicly accessible URL (e.g. authentik.mydomain.tld) for the redirects, etc. For vikunja, this would be the authurl.

Again, only for something like traefik forward auth would you use the internal authentik-public network, and even then, you would need to set up the public URL as the redirect.

Authelia has a really good example of the concepts here: https://www.authelia.com/integration/proxies/traefik/