Persistent iptables rules (or load iptables rules at startup)

Hi guys!

How can I setup iptables rules on startup? I cannot leave some ports open to wide public (like nagios agent). I did not find any way to do it, without iptables working this cannot be used in production.

I tried this solution: https://github.com/rancher/os/issues/446#issuecomment-131446590
But it does not work - at the time the script is started, the network is not reachable and system-docker is unable to pull the busybox image to start.

Please help!

This is a nightmare.

I have solved the issue with busybox pull - I just add io.rancher.os.after: wait-for-network, then it works (it needs to wait for eth0 initialization).

But other problems:

  • recent version of busybox now does not have iptables and iptable-restore, I try to mount it from the host filesystem
  • while booting for the first time, /opt is not available to the service, so it fails, because files are not found

I have tried this solution then:

`#cloud-config
hostname: rancher-os
ssh_authorized_keys:

  • ssh-rsa AAAAxxxx…
    write_files:
  • path: /opt/rancher/init/iptables.sh
    permissions: "0755"
    owner: "root:root"
    content: |
    #!/bin/bash
    iptables -F
    iptables -P INPUT DROP
    iptables -P FORWARD ACCEPT
    iptables -P OUTPUT ACCEPT
    iptables -A INPUT -i lo -j ACCEPT
    iptables -A INPUT -i eth1 -j ACCEPT
    iptables -A INPUT -i docker0 -j ACCEPT
    iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
    iptables -A INPUT -i eth0 -p tcp -m multiport --dports 2222 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
    iptables -A FORWARD -i docker0 -o eth1 -j ACCEPT
    iptables -A FORWARD -i eth1 -o docker0 -j ACCEPT
    iptables -A FORWARD -i eth0 -o docker0 -j ACCEPT
    iptables -A FORWARD -i docker0 -o eth0 -j ACCEPT
    iptables -I INPUT -p icmp --icmp-type destination-unreachable -j ACCEPT
    iptables -I INPUT -p icmp --icmp-type source-quench -j ACCEPT
    iptables -I INPUT -p icmp --icmp-type time-exceeded -j ACCEPT
    iptables -I INPUT -p icmp --icmp-type echo-request -j ACCEPT
  • path: /home/rancher/.docker/config.json
    permissions: "0660"
    encoding: b64
    content: xxxx
  • path: /etc/ssh/sshd_config
    permissions: "0644"
    owner: root:root
    content: |
    Port 2222
    AuthorizedKeysFile .ssh/authorized_keys
    UsePrivilegeSeparation sandbox
    ClientAliveInterval 180
    Subsystem sftp /usr/libexec/sftp-server
    UseDNS no
    PermitRootLogin no
    AllowGroups docker
    rancher:
    cloud_init:
    datasources:
    • ec2
      network:
      dns:
      nameserver:
      • 8.8.4.4
      • 4.2.2.3
        interfaces:
        eth0:
        dhcp: true
        eth1:
        address: $V4_PRIVATE_IP/16
        mtu: 1450
        state:
        fstype: auto
        dev: LABEL=RANCHER_STATE
        autoformat:
    • /dev/vda
      services:
      init_script:
      image: busybox
      net: host
      uts: host
      pid: host
      ipc: host
      privileged: true
      volumes_from:
      • user-volumes
        volumes:
      • /sbin/iptables:/usr/bin/iptables:ro
        labels:
        io.rancher.os.scope: system
        io.rancher.os.after: wait-for-network, cloud-init
        command: /opt/rancher/init/iptables.sh`

With this example, when I boot first time, I get error that /opt/rancher/init/iptables.sh does not exist. From now on, when I reboot, /opt/rancher/init/iptables.sh executes OK, but I get kernel panic each time. Apparently it does not like launching iptables command from within busybox container.

Please help!

Maybe you could use an alpine linux container instead of busybox?

I would like a native solution to add / load custom iptables rules to RancherOS.

Set the rules via the cloud-config. Try something like the following, where a script file is created and run when the network is up (The magic lines are 9-11 and the write_files part):

EXTRA_CMDLINE: /init
hostname: RancherUI
rancher:
  console: ubuntu
  docker:
    engine: docker-17.12.1-ce
  environment:
    EXTRA_CMDLINE: /init
  network:
    post_cmds:
    - /var/lib/iptables/rules.sh post_cmds # run command after the network is set up
  resize_device: /dev/vda
  services_include:
    kvm-vm-tools: true
  state:
    dev: LABEL=RANCHER_STATE
    wait: true
  sysctl:
    vm.max_map_count: 524288
runcmd:
- echo deadline > /sys/block/sda/queue/scheduler # deadline scheduler is faster on ssds than the default
- ulimit -n 80000
ssh_authorized_keys:
- ssh-rsa some-ssh-public-key
write_files:
- container: network
  content: |+
    #!/bin/bash
    set -ex
    echo ui >> /var/log/net.log
    iptables -A INPUT -i lo -j ACCEPT # Loopback
    iptables -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT # Outgoing
    iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT # PING
    iptables -A INPUT -s 172.17.0.0/16 -j ACCEPT # Docker internal
    iptables -N DOCKER-USER
    iptables -I DOCKER-USER 1 -j DROP
    iptables -I DOCKER-USER 1 -j LOG
    iptables -I DOCKER-USER 1 -s 213.133.96.0/20 -p udp -m udp --sport 53 -j RETURN # DNS
    iptables -I DOCKER-USER 1 -p tcp -m tcp --sport 443 -j RETURN # HTTPS
    iptables -I DOCKER-USER 1 -s 172.17.0.0/16 -j RETURN # Docker internal
    iptables -A INPUT -j LOG
    iptables -P INPUT DROP
    iptables -P FORWARD ACCEPT
    # the last line of the file needs to be a blank line or a comment
  owner: root:root
  path: /var/lib/iptables/rules.sh
  permissions: "0755"

Hi, your iptables rules are interesting and would love to use it at my VPS.
I am newbie and learning.

Please, could you explain what does these rules do and what should I change to suits my VPS in general e.g. IPs etc?

Apart of IPtables I have another questions:
why is it good to use: resize_device