Docker Swarm + Traefik under DDoS attack

292 views Asked by At

env:

  • Docker Swarm
  • traefik
  • several services for listening 80 and 443 traffic in xxx.domain.com, yyy.domain.com and etc
  • Hetzner hosting

Domains have anti DDoS protection like Cloudflare But we have attacks by IP address and domain https://static.IP.clients.your-server.de (seems it is provided by default from Hetzner)

It is attack on 404 page - because we don't have service:

version: '3.3'

services:
  traefik:
    image: traefik:v2.10.6
    ports:
      - 80:80
      - 443:443
    deploy:
      placement:
        constraints:
          - node.labels.traefik-public.traefik-public-certificates == true
      labels:
        - traefik.enable=true
        - traefik.docker.network=traefik-public
        - traefik.constraint-label=traefik-public
        - traefik.http.middlewares.https-redirect.redirectscheme.scheme=https
        - traefik.http.middlewares.https-redirect.redirectscheme.permanent=true
        - traefik.http.routers.traefik-public-http.rule=Host(`${DOMAIN?Variable not set}`)
        - traefik.http.routers.traefik-public-http.entrypoints=http
        - traefik.http.routers.traefik-public-http.middlewares=https-redirect
        - traefik.http.routers.traefik-public-https.rule=Host(`${DOMAIN?Variable not set}`)
        - traefik.http.routers.traefik-public-https.entrypoints=https
        - traefik.http.routers.traefik-public-https.tls=true
        - traefik.http.routers.traefik-public-https.service=api@internal
        - traefik.http.routers.traefik-public-https.tls.certresolver=le
        - traefik.http.routers.traefik-public-https.middlewares=admin-auth
        - traefik.http.services.traefik-public.loadbalancer.server.port=8080



    volumes:
      # Add Docker as a mounted volume, so that Traefik can read the labels of other services
      - /var/run/docker.sock:/var/run/docker.sock:ro
      # Mount the volume to store the certificates
      - traefik-public-certificates:/certificates
    command:
      # Enable Docker in Traefik, so that it reads labels from Docker services
      - --providers.docker
      # Add a constraint to only use services with the label "traefik.constraint-label=traefik-public"
      - --providers.docker.constraints=Label(`traefik.constraint-label`, `traefik-public`)
      # Do not expose all Docker services, only the ones explicitly exposed
      - --providers.docker.exposedbydefault=false
      # Enable Docker Swarm mode
      - --providers.docker.swarmmode
      # Create an entrypoint "http" listening on port 80
      - --entrypoints.http.address=:80
      # Create an entrypoint "https" listening on port 443
      - --entrypoints.https.address=:443
      # Create the certificate resolver "le" for Let's Encrypt, uses the environment variable EMAIL
      - --certificatesresolvers.le.acme.email=${EMAIL?Variable not set}
      # Store the Let's Encrypt certificates in the mounted volume
      - --certificatesresolvers.le.acme.storage=/certificates/acme.json
      # Use the TLS Challenge for Let's Encrypt
      - --certificatesresolvers.le.acme.tlschallenge=true
      # Enable the access log, with HTTP requests
      - --accesslog
      # Enable the Traefik log, for configurations and errors
      - --log
      # Enable the Dashboard and API
      - --api
    networks:
      # Use the public network created to be shared between Traefik and
      # any other service that needs to be publicly available with HTTPS
      - traefik-public

volumes:
  # Create a volume to store the certificates, there is a constraint to make sure
  # Traefik is always deployed to the same Docker node with the same volume containing
  # the HTTPS certificates
  traefik-public-certificates:

networks:
  # Use the previously created public network "traefik-public", shared with other
  # services that need to be publicly available via this Traefik
  traefik-public:
    external: true

We can't hide our real server IP - so we have attack by IP.

Is it possible to accept requests only for domain.com and ***.domain.com?

We do not need 404 error on requests by IP - because DDoS is also possible with 404 error too

2

There are 2 answers

0
Fer Mena On BEST ANSWER

There's no much info but I will share my 2 cents here.

  • Talk with your hosting company to explore techniques to block requests from IP addresses from all countries except the one or ones you have business with, since our domain ends in DE I assume can just allow requests from DE.
  • As an alternative I would try with traefik this: https://plugins.traefik.io/plugins/62947313ffc0cd18356a97ca/geo-block after making all services private except for traefik. This sounds super easy so I really hope this works.
  • You need to put all your services behind a DMZ, they won't have a public IP again, create a New LoadBalancer (nginx, or something provided by your cloud provider), the LoadBalancer's public IP needs to be associated to all the domains and subdomains you need, this can be done in your DNS Manager.
  • Then in the configuration of your LoadBalancer(not sure if you can do this in Traefik) you need to check for the VHOST (domain or subdomain) and redirect those requests to the services that you previously made internal.

If you pick something like NGINX the config look something like this:

server {
listen 80;
   root /var/www/html/example1.com;
   index index.html;
   server_name example1.com;
   location / {
       try_files $uri $uri/ =404;
   }
}

server {
   listen 80;
   root /var/www/html/example2.com;
   index index.html;
   server_name example2.com;
   location / {
       try_files $uri $uri/ =404;
   }
}

I took the snippet from here: https://fedingo.com/how-to-host-multiple-domains-on-one-server-in-nginx/

0
perpetual-light On

3 Things:

A loadbalancer like Traefik should only route to the web server that is configured for the given domain or subdomain. It sounds like your DNS may be messed up. Check to see if there are entries for the IP behind the load balancer and remove them in favor of the load balancer itself.

This is accomplished through your domain provider or a delegate DNS service depending on your setup.

If the load balancer is configured properly then it should ignore requests for resources at a static IP.

The other thing is that some hosting providers will provide a separate domain naming scheme such as 11-11-11-11.internal.hosting.dns where 11-11-11-11 is the IP of the internal VM/Server. The hosting platform should provide options to disable or conceal this from the public at your request. If not then it is upto you to filter this from the web server configuration which you have not included.

Also, I see a traefik-public network in your swarm configuration. This could be the actual public facing entrypoint or it could be something that should be refactored to expose internal api's internally only. More information about your setup would be required to say for sure.