This is a live blogging of the installation process of DFIR-IRIS on FreeBSD 14.0-RELEASE using Jails and Jailer.
The main requirements are:
- Nginx
- PostgreSQL
- Python
- Some random dependencies we saw in the Dockerfile
I assume you already have nginx up and running, we will just be setting up a vhost under the domain name dfir.cert.am
. Don’t worry, this is INSIDE our infrastructure, you will not be able to connect to it 🙂
Initial Setup
First we create a jail named iris0
, using Jailer:
jailer create iris0
Next we install the required software inside of the jail. Looks like everything is available in FreeBSD packages:
jailer console iris0
pkg install \ nginx \ python39 \ py39-pip \ gnupg \ 7-zip \ rsync \ postgresql12-client \ git-tiny \ libxslt \ rust \ acme.sh
Installing DFIR-IRIS
Since we’re using FreeBSD, we’ll be doing things the right way instead of the Docker way, so we will be running IRIS as a user, not as root.
pw user add iris -m
Next we setup some directories and checkout the repo
root@iris0:~ # pw user add iris -m
root@iris0:~ # su - iris iris@iris0:~ $ git clone --branch v2.4.7 https://github.com/dfir-iris/iris-web.git iris-web
Finally, we install some python dependencies using pip.
iris@iris0:~ $ cd iris-web/source
iris@iris0:~/iris-web/source $ pip install -r requirements.txt
Now we have to configure the
file based on our needs, I will post my version of it, I hope it helps.
env
# -- DATABASE export POSTGRES_USER=postgres export POSTGRES_PASSWORD=postgres export POSTGRES_DB=iris_db export POSTGRES_ADMIN_USER=iris export POSTGRES_ADMIN_PASSWORD=longpassword export POSTGRES_SERVER=localhost export POSTGRES_PORT=5432 # -- IRIS export DOCKERIZED=0 export IRIS_SECRET_KEY=verylongsecret export IRIS_SECURITY_PASSWORD_SALT=verylongsalt export IRIS_UPSTREAM_SERVER=app # these are for docker, you can ignore export IRIS_UPSTREAM_PORT=8000 # -- WORKER export CELERY_BROKER=amqp://localhost # Set to your rabbitmq instance # Change these as you need them. # -- AUTH #IRIS_AUTHENTICATION_TYPE=local ## optional #IRIS_ADM_PASSWORD=MySuperAdminPassword! #IRIS_ADM_API_KEY=B8BA5D730210B50F41C06941582D7965D57319D5685440587F98DFDC45A01594 #IRIS_ADM_EMAIL=admin@localhost #IRIS_ADM_USERNAME=administrator # requests the just-in-time creation of users with ldap authentification (see https://github.com/dfir-iris/iris-web/issues/203) #IRIS_AUTHENTICATION_CREATE_USER_IF_NOT_EXIST=True # the group to which newly created users are initially added, default value is Analysts #IRIS_NEW_USERS_DEFAULT_GROUP= # -- LISTENING PORT #INTERFACE_HTTPS_PORT=443
Configuring HTTPS
We can use acme.sh to issue a TLS certificate from Lets Encrypt.
root@iris0:~ # acme.sh --set-default-ca --server letsencrypt root@iris0:~ # acme.sh --issue -d dfir.cert.am --standalone root@iris0:~ # acme.sh -i -d dfir.cert.am --fullchain-file /usr/local/etc/ssl/dfir.cert.am/fullchain.pem --key-file /usr/local/etc/ssl/dfir.cert.am/key.pem --reloadcmd 'service nginx reload'
Setup nginx
DFIR-IRIS provides a nginx configuration template at nginx.conf, we will be using that, with a little bit of modifications.
The final nginx.conf will look like this:
#user nobody; worker_processes 1; # This default error log path is compiled-in to make sure configuration parsing # errors are logged somewhere, especially during unattended boot when stderr # isn't normally logged anywhere. This path will be touched on every nginx # start regardless of error log location configured here. See # https://trac.nginx.org/nginx/ticket/147 for more info. # #error_log /var/log/nginx/error.log; # #pid logs/nginx.pid; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; # Things needed/recommended by DFIR-IRIS map $request_uri $csp_header { default "default-src 'self' https://analytics.dfir-iris.org; script-src 'self' 'unsafe-inline' https://analytics.dfir-iris.org; style-src 'self' 'unsafe-inline';"; } server_tokens off; sendfile on; tcp_nopush on; tcp_nodelay on; types_hash_max_size 2048; types_hash_bucket_size 128; proxy_headers_hash_max_size 2048; proxy_headers_hash_bucket_size 128; proxy_buffering on; proxy_buffers 8 16k; proxy_buffer_size 4k; client_header_buffer_size 2k; large_client_header_buffers 8 64k; client_body_buffer_size 64k; client_max_body_size 100M; reset_timedout_connection on; keepalive_timeout 90s; client_body_timeout 90s; send_timeout 90s; client_header_timeout 90s; fastcgi_read_timeout 90s; # WORKING TIMEOUT FOR PROXY CONF proxy_read_timeout 90s; uwsgi_read_timeout 90s; gzip off; gzip_disable "MSIE [1-6]\."; # FORWARD CLIENT IDENTITY TO SERVER proxy_set_header HOST $http_host; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # FULLY DISABLE SERVER CACHE add_header Last-Modified $date_gmt; add_header 'Cache-Control' 'no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0'; if_modified_since off; expires off; etag off; proxy_no_cache 1; proxy_cache_bypass 1; # SSL CONF, STRONG CIPHERS ONLY ssl_protocols TLSv1.2 TLSv1.3; ssl_prefer_server_ciphers on; ssl_certificate /usr/local/etc/ssl/dfir.cert.am/fullchain.pem; ssl_certificate_key /usr/local/etc/ssl/dfir.cert.am/key.pem; ssl_ecdh_curve secp521r1:secp384r1:prime256v1; ssl_buffer_size 4k; # DISABLE SSL SESSION CACHE ssl_session_tickets off; ssl_session_cache none; server { listen 443 ssl server_name dfir.cert.am; root /www/data; index index.html; error_page 500 502 503 504 /50x.html; add_header Content-Security-Policy $csp_header; # SECURITY HEADERS add_header X-XSS-Protection "1; mode=block"; add_header X-Frame-Options DENY; add_header X-Content-Type-Options nosniff; # max-age = 31536000s = 1 year add_header Strict-Transport-Security "max-age=31536000: includeSubDomains" always; add_header Front-End-Https on; location / { proxy_pass http://localhost:8000; location ~ ^/(manage/templates/add|manage/cases/upload_files) { keepalive_timeout 10m; client_body_timeout 10m; send_timeout 10m; proxy_read_timeout 10m; client_max_body_size 0M; proxy_request_buffering off; proxy_pass http://localhost:8000; } location ~ ^/(datastore/file/add|datastore/file/add-interactive) { keepalive_timeout 10m; client_body_timeout 10m; send_timeout 10m; proxy_read_timeout 10m; client_max_body_size 0M; proxy_request_buffering off; proxy_pass http://localhost:8000; } } location /socket.io { proxy_set_header Host $http_host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_http_version 1.1; proxy_buffering off; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "Upgrade"; proxy_pass http://localhost:8000/socket.io; } } }
Setup PostgreSQL
I assume you know how to do this 🙂 You don’t need to configure a separate user, by the looks of it, IRIS likes to do that itself. Thanks to Jails I was able to run a separate PostgreSQL instance in the iris0
jail.
P.S. If you are running PostgreSQL inside a jail, make sure that the following variables are set in your jail configuration
sysvshm = new; sysvmsg = new;
Running DFIR-IRIS
Now that everything is up and running, we just need to run DFIR-IRIS and it will create the database, needed users, an administration account, etc.
su - iris cd ~/iris-web/source . ../.env ~/.local/bin/gunicorn app:app --worker-class eventlet --bind 0.0.0.0:8000 --timeout 180 --worker-connections 1000 --log-level=debug
Assuming everything is fine, now we can setup a rc.d
service script to make sure it runs at boot.
For that I wrote two files, the service itself and a helper start.sh
script
rc.d
script at /usr/local/etc/rc.d/iris
#!/bin/sh # PROVIDE: iris # REQUIRE: NETWORKING # KEYWORD: . /etc/rc.subr name="iris" rcvar="iris_enable" load_rc_config ${name} : ${iris_enable:=no} : ${iris_path:="/usr/local/iris"} : ${iris_gunicorn:="/usr/local/bin/gunicorn"} : ${iris_env="iris_gunicorn=${iris_gunicorn}"} logfile="${iris_path}/iris.log" pidfile="/var/run/${name}/iris.pid" iris_user="iris" iris_chdir="${iris_path}/source" iris_command="${iris_path}/start.sh" command="/usr/sbin/daemon" command_args="-P ${pidfile} -T ${name} -o ${logfile} ${iris_command}" run_rc_command "$1"
and the helper script at /home/iris/iris-web/start.sh
#!/bin/sh export HOME=$(getent passwd `whoami` | cut -d : -f 6) . ../.env ${iris_gunicorn} app:app --worker-class eventlet --bind 0.0.0.0:8000 --timeout 180 --worker-connections 128
now we set some variables in rc.conf
using sysrc
and we can start the service.
sysrc iris_enable="YES" sysrc iris_path="/home/iris/iris-web" sysrc iris_gunicorn="/home/iris/.local/bin/gunicorn"
Finally, we can start DFIR-IRIS as a service.
service iris start
Aaaaand we’re done 🙂
Thank you for reading!
There are some issues that I’d like to tackle, for example, service iris stop
doesn’t work, and it would be nice if we ported all of the dependencies into Ports, but for now, this seems to be working fine.
Special thanks to the DFIR-IRIS team for creating this cool platform!
That’s all folks…