Configuring Falco with gVisor

Edit this page Create issue

Installation

First, install gVisor and Falco on the machine. Run runsc --version and check that runsc version release-20220704.0 or newer is reported. Run falco --version and check that Falco version reports 0.32.1 or higher.

Once both are installed, you can configure gVisor to connect to Falco whenever a new sandbox is started. The first command below generates a configuration file containing a list of trace points that Falco is interested in receiving. This file is passed to gVisor during container startup so that gVisor connects to Falco before the application starts. The second command installs runsc as a Docker runtime pointing it to the configuration file we just generated:

falco --gvisor-generate-config | sudo tee /etc/falco/pod-init.json
sudo runsc install --runtime=runsc-falco -- --pod-init-config=/etc/falco/pod-init.json
sudo systemctl restart docker

Note: Between steps 1 and 2 above, edit the pod-init.json file to add ignore_setup_error to the sink options (this will be fixed in the next Falco release). The file will look like this:

      "sinks" : [
         {
            "config" : {
               "endpoint" : "/tmp/gvisor.sock"
            },
            "name" : "remote",
            "ignore_setup_error": true   <== ADD THIS LINE
         }
      ]

gVisor is now configured. Next, let’s start Falco and tell it to enable gVisor monitoring. You should use the same command line that you normally use to start Falco with these additional flags:

  • --gvisor-config: path to the gVisor configuration file, in our case /etc/falco/pod-init.json.
  • --gvisor-root: path to the --root flag that docker uses with gVisor, normally: /var/run/docker/runtime-runc/moby.

For our example, let’s just start with the default settings and rules:

sudo falco \
  -c /etc/falco/falco.yaml \
  --gvisor-config /etc/falco/pod-init.json \
  --gvisor-root /var/run/docker/runtime-runc/moby

Note: If you get Error: Cannot find runsc binary, make sure runsc is in the PATH.

From this point on, every time a gVisor sandbox starts, it connects to Falco to send trace points occurring inside the container. Those are translated into Falco events that are processed by the rules you have defined. If you used the command above, the configuration files are defined in /etc/falco/faco_rules.yaml and /etc/falco/faco_rules.local.yaml (where you can add your own rules).

Triggering Falco Events

Let’s run something interesting inside a container to see a few rules trigger in Falco. Package managers, like apt, don’t normally run inside containers in production, and often indicate that an attacker is trying to install tools to expose the container. To detect such cases, the default set of rules trigger an Error event when the package manager is invoked. Let’s see it in action, first start a container and run a simple apt command:

sudo docker run --rm --runtime=runsc-falco -ti ubuntu
$ apt update

In the terminal where falco is running, you should see in the output many Error Package management process launched events. Here is one of the events informing that a package manager was invoked inside the container:

{
  "output": "18:39:27.542112944: Error Package management process launched in container (user=root user_loginuid=0 command=apt apt update container_id=1473cfd51410 container_name=sad_wu image=ubuntu:latest) container=1473cfd51410 pid=4 tid=4",
  "priority": "Error",
  "rule": "Launch Package Management Process in Container",
  "source": "syscall",
  "tags": [
    "mitre_persistence",
    "process"
  ],
  "time": "2022-08-02T18:39:27.542112944Z",
  "output_fields": {
    "container.id": "1473cfd51410",
    "container.image.repository": "ubuntu",
    "container.image.tag": "latest",
    "container.name": "sad_wu",
    "evt.time": 1659465567542113000,
    "proc.cmdline": "apt apt update",
    "proc.vpid": 4,
    "thread.vtid": 4,
    "user.loginuid": 0,
    "user.name": "root"
  }
}

As you can see, it’s warning that apt update command was ran inside container sad_wu, and gives more information about the user, TID, image name, etc. There are also rules that trigger when there is a write under / and other system directories that are normally part of the image and shouldn’t be changed. If we proceed with installing packages into the container, apart from the event above, there are a few other events that are triggered. Let’s execute apt-get install -y netcat and look at the output:

{
  "output": "18:40:42.192811725: Warning Sensitive file opened for reading by non-trusted program (user=root user_loginuid=0 program=dpkg-preconfigure command=dpkg-preconfigure /usr/sbin/dpkg-preconfigure --apt file=/etc/shadow parent=sh gparent=<NA> ggparent=<NA> gggparent=<NA> container_id=1473cfd51410 image=ubuntu) container=1473cfd51410 pid=213 tid=213",
  "priority": "Warning",
  "rule": "Read sensitive file untrusted",
  "source": "syscall",
  "tags": [
    "filesystem",
    "mitre_credential_access",
    "mitre_discovery"
  ],
}

{
  "output": "18:40:42.494933664: Error File below / or /root opened for writing (user=root user_loginuid=0 command=tar tar -x -f - --warning=no-timestamp parent=dpkg-deb file=md5sums program=tar container_id=1473cfd51410 image=ubuntu) container=1473cfd51410 pid=221 tid=221",
  "priority": "Error",
  "rule": "Write below root",
  "source": "syscall",
  "tags": [
    "filesystem",
    "mitre_persistence"
  ],
}

The first event is raised as a Warning when /etc/shadow is open by the package manager to inform that a sensitive file has been open for read. The second one triggers an Error when the package manager tries to untar a file under the root directory. None of these actions are expected from a webserver that is operating normally and should raise security alerts.

You can also install falcosidekick and falcosidekick-ui for better ways to visualize the events.

Now you can configure the rules and run your containers using gVisor and Falco.