├── .github ├── ISSUE_TEMPLATE │ ├── 1_FEATURE.yml │ ├── 2_ISO_BUG.yml │ └── 3_DOCKER_BUG.yml └── workflows │ └── docker-build.yml ├── .gitignore ├── LICENSE ├── README.rst ├── build-debian-live.sh ├── doc ├── example-logs │ ├── PSEXEC-RCE-network-monitoring-logs-example.json │ ├── eve-alert.json │ ├── eve-anomaly.json │ ├── eve-fileinfo.json │ ├── eve-flow.json │ ├── eve-http.json │ ├── eve-krb5.json │ ├── eve-smb.json │ └── eve-tls.json └── images │ ├── Distro-1.png │ ├── Distro-2.png │ ├── Hunt-Context-2.png │ ├── Hunt-Filtersets-1.png │ ├── Hunt-context-1.png │ ├── Overview-1.png │ ├── Overview-KRB5.png │ ├── Overview-filetransactions.png │ ├── Supplemental-info.png │ └── Suricata-Generated-Eventsv2-source.webp ├── docker ├── Arkime │ ├── Arkime.dockerfile │ ├── arkimepcapread-selks-config.ini │ └── start-arkimeviewer.sh ├── README.md ├── compose.yml ├── containers-data │ ├── cron-jobs │ │ ├── README.md │ │ └── daily │ │ │ ├── scirius-update-suri-rules.sh │ │ │ └── suricata-logrotate.sh │ ├── logstash │ │ ├── conf.d │ │ │ └── logstash.conf │ │ └── templates │ │ │ └── elasticsearch7-template.json │ ├── nginx │ │ ├── conf.d │ │ │ └── selks6.conf │ │ └── nginx.conf │ └── suricata │ │ └── etc │ │ ├── new_entrypoint.sh │ │ └── selks6-addin.yaml ├── easy-setup.sh └── scripts │ ├── cleanup.sh │ └── readpcap.sh ├── install-deps.sh ├── kubernetes ├── README.md ├── arkime │ ├── arkime-configmap.yaml │ ├── arkime-deployment.yaml │ ├── arkime-pv.yaml │ ├── arkime-pvc.yaml │ ├── arkime-secret.yaml │ └── arkime-service.yaml ├── common │ ├── logging-ns.yaml │ ├── networkpolicies.yaml │ ├── storageclass.yaml │ └── suricata-ns.yaml ├── elasticsearch │ ├── elasticsearch-pv.yaml │ ├── elasticsearch-pvc.yaml │ ├── elasticsearch-service.yaml │ └── elasticsearch-statefulset.yaml ├── evebox │ ├── evebox-deployment.yaml │ └── evebox-service.yaml ├── fluentd_fluent-bit │ ├── Dockerfile │ ├── fluentbit-configmap.yaml │ ├── fluentbit-daemonset.yaml │ ├── fluentbit-service.yaml │ ├── fluentd-configmap.yaml │ ├── fluentd-deployment.yaml │ └── fluentd-service.yaml ├── install.sh ├── kibana │ ├── kibana-dashboards-job.yaml │ ├── kibana-deployment.yaml │ └── kibana-service.yaml ├── logstash_filebeat │ ├── filebeat-configmap.yaml │ ├── filebeat-daemonset.yaml │ ├── logstash-configmap.yaml │ ├── logstash-service.yaml │ └── logstash-statefulset.yaml ├── nginx │ ├── nginx-configmap.yaml │ ├── nginx-deployment.yaml │ ├── nginx-ingress.yaml │ ├── nginx-owasp-configmap.yaml │ ├── nginx-owasp-deployment.yaml │ ├── nginx-owasp-service.yaml │ └── nginx-service.yaml ├── scirius │ ├── scirius-cronjob.yaml │ ├── scirius-deployment.yaml │ ├── scirius-pv.yaml │ ├── scirius-pvc.yaml │ ├── scirius-secret.yaml │ └── scirius-service.yaml └── suricata │ ├── suricata-configmap.yaml │ ├── suricata-cronjob.yaml │ ├── suricata-daemonset.yaml │ ├── suricata-pv.yaml │ ├── suricata-pvc.yaml │ └── suricata-stdout.yaml ├── scripts ├── SELKS3-SELKS4 │ ├── README.rst │ └── SN-S3-S4-Upgrade.sh ├── SELKS4-SELKS5 │ ├── README.rst │ ├── SN-S4-S5-ES-Reindex.sh │ └── SN-S4-S5-Upgrade.sh └── SELKS5-SELKS6 │ ├── README.rst │ └── SN-S5-S6-Upgrade.sh └── staging ├── config └── hooks │ └── live │ ├── all_chroot_update-initramfs.sh │ ├── chroot-inside-Debian-Live.hook.chroot │ ├── menues-changes-live-custom-kernel-choice.hook.binary │ └── menues-changes.hook.binary ├── data └── moloch │ └── etc │ └── molochpcapread-selks-config.ini ├── etc ├── conky │ └── conky.conf ├── default │ └── evebox ├── iceweasel │ └── profile │ │ └── bookmarks.html ├── issue.net ├── logrotate.d │ └── suricata ├── logstash │ ├── conf.d │ │ └── logstash.conf │ ├── elasticsearch5-template.json │ ├── elasticsearch6-template.json │ └── elasticsearch7-template.json ├── motd ├── profile.d │ └── pythonpath.sh └── systemd │ └── system │ ├── molochpcapread-selks.service │ └── molochviewer-selks.service ├── splash.png ├── usr └── share │ ├── applications │ ├── Evebox.desktop │ └── Scirius.desktop │ └── polkit-1 │ ├── actions │ ├── org.stamusnetworks.firsttimesetup.policy │ ├── org.stamusnetworks.setupidsinterface.policy │ └── org.stamusnetworks.update.policy │ └── rules.d │ └── org.stamusnetworks.rules └── wallpaper └── joy-wallpaper_1920x1080.svg /.github/ISSUE_TEMPLATE/1_FEATURE.yml: -------------------------------------------------------------------------------- 1 | name: ✨✨ Feature Request 2 | description: File a feature request 3 | title: "✨✨ " 4 | labels: [Enhancement, Triage] 5 | body: 6 | 7 | 8 | - type: checkboxes 9 | attributes: 10 | label: Is there an existing feature request that has already been created? 11 | description: Please search to see if a feature request already exists. 12 | options: 13 | - label: I have searched the exiting features requests 14 | required: true 15 | 16 | - type: textarea 17 | attributes: 18 | label: Is your feature request related to a problem? Please describe. 19 | description: A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 20 | validations: 21 | required: false 22 | 23 | - type: textarea 24 | attributes: 25 | label: Describe the solution you would like? 26 | description: A clear and concise description of what you want to happen. 27 | validations: 28 | required: true 29 | 30 | - type: textarea 31 | attributes: 32 | label: Alternative Solutions 33 | description: A clear and concise description of any alternative solutions or features you've considered. 34 | validations: 35 | required: false 36 | 37 | - type: textarea 38 | attributes: 39 | label: Additional Context 40 | description: Add any other context or screenshots about the feature request here. 41 | validations: 42 | required: false 43 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/2_ISO_BUG.yml: -------------------------------------------------------------------------------- 1 | name: 🐞💿 Bug on the ISO version 2 | description: File a bug/issue 3 | title: "🐞💿 <title>" 4 | labels: [Bug, Triage] 5 | body: 6 | 7 | 8 | - type: checkboxes 9 | attributes: 10 | label: Is there an existing issue for this? 11 | description: Please search to see if an issue already exists for the bug you encountered. 12 | options: 13 | - label: I have searched the existing issues 14 | required: true 15 | 16 | - type: textarea 17 | attributes: 18 | label: Current Behavior 19 | description: A concise description of what you're experiencing. 20 | validations: 21 | required: false 22 | 23 | - type: textarea 24 | attributes: 25 | label: Expected Behavior 26 | description: A concise description of what you expected to happen. 27 | validations: 28 | required: false 29 | 30 | - type: textarea 31 | attributes: 32 | label: Steps To Reproduce 33 | description: Steps to reproduce the behavior. 34 | placeholder: | 35 | 1. In this environment... 36 | 2. With this config... 37 | 3. Run '...' 38 | 4. See error... 39 | validations: 40 | required: false 41 | 42 | - type: textarea 43 | attributes: 44 | label: Anything else? 45 | description: | 46 | Links? References? Anything that will give us more context about the issue you are encountering! 47 | 48 | Tip: You can attach images or log files by clicking this area to highlight it and then dragging files in. 49 | validations: 50 | required: false 51 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/3_DOCKER_BUG.yml: -------------------------------------------------------------------------------- 1 | name: 🐞🐋Bug on the Docker version 2 | description: File a bug/issue related to the docker-based implementation of SELKS 3 | title: "🐞🐋 <title>" 4 | labels: [Bug, Docker, Triage] 5 | body: 6 | 7 | 8 | - type: checkboxes 9 | attributes: 10 | label: Is there an existing issue for this? 11 | description: Please search to see if an issue already exists for the bug you encountered. 12 | options: 13 | - label: I have searched the existing issues 14 | required: true 15 | 16 | - type: textarea 17 | attributes: 18 | label: Current Behavior 19 | description: A concise description of what you're experiencing. 20 | validations: 21 | required: false 22 | 23 | - type: textarea 24 | attributes: 25 | label: Expected Behavior 26 | description: A concise description of what you expected to happen. 27 | validations: 28 | required: false 29 | 30 | - type: textarea 31 | attributes: 32 | label: Steps To Reproduce 33 | description: Steps to reproduce the behavior. 34 | placeholder: | 35 | 1. In this environment... 36 | 2. With this config... 37 | 3. Run '...' 38 | 4. See error... 39 | validations: 40 | required: false 41 | 42 | - type: input 43 | id: docker-version 44 | attributes: 45 | label: Docker version 46 | description: Output of `docker -v ` 47 | placeholder: ex. Docker version 20.10.10, build b485636 48 | validations: 49 | required: true 50 | 51 | - type: input 52 | id: docker-compose-version 53 | attributes: 54 | label: Docker version 55 | description: Output of `docker-compose -v ` 56 | placeholder: ex. docker-compose version 1.29.2, build 5becea4c 57 | validations: 58 | required: true 59 | 60 | - type: input 61 | id: os-version 62 | attributes: 63 | label: OS Version 64 | description: Output of `lsb_release -d` 65 | validations: 66 | required: true 67 | 68 | - type: textarea 69 | id: env-file 70 | attributes: 71 | label: Content of the environnement File 72 | description: Output of `cat SELKS/docker/.env` 73 | validations: 74 | required: true 75 | 76 | - type: textarea 77 | id: selks-version 78 | attributes: 79 | label: Version of SELKS 80 | description: Output of `git log -1` 81 | validations: 82 | required: true 83 | 84 | - type: textarea 85 | attributes: 86 | label: Anything else? 87 | description: | 88 | Links? References? Anything that will give us more context about the issue you are encountering! 89 | 90 | Tip: You can attach images or log files by clicking this area to highlight it and then dragging files in. 91 | validations: 92 | required: false 93 | -------------------------------------------------------------------------------- /.github/workflows/docker-build.yml: -------------------------------------------------------------------------------- 1 | name: Build ArkimeViewer docker Image 2 | 3 | on: 4 | # All thoses triggers might be too much, subject to change 5 | push: 6 | pull_request: 7 | release: 8 | types: [published, created, edited] 9 | label: 10 | types: [created, edited] 11 | workflow_dispatch: 12 | 13 | jobs: 14 | push_to_registry: 15 | name: Push Docker image to GitHub Container Registry 16 | runs-on: ubuntu-latest 17 | permissions: 18 | packages: write 19 | contents: read 20 | steps: 21 | - 22 | name: Check out the repo 23 | uses: actions/checkout@v2 24 | 25 | - 26 | name: Set up Docker Buildx 27 | uses: docker/setup-buildx-action@v1 28 | 29 | - 30 | name: Cache Docker layers 31 | uses: actions/cache@v2 32 | with: 33 | path: /tmp/.buildx-cache 34 | key: ${{ runner.os }}-buildx-${{ github.sha }} 35 | restore-keys: | 36 | ${{ runner.os }}-buildx- 37 | 38 | - 39 | name: Log in to GitHub Container Registry 40 | uses: docker/login-action@v1 41 | with: 42 | registry: ghcr.io 43 | username: ${{ github.actor }} 44 | password: ${{ secrets.GITHUB_TOKEN }} 45 | 46 | - 47 | name: PrepareReg Names 48 | run: | 49 | # Change all uppercase to lowercase 50 | OWNER=$(echo ${{ github.repository_owner }} | tr '[A-Z]' '[a-z]') 51 | 52 | # Strip git ref prefix from version 53 | VERSION=$(echo "${{ github.ref }}" | sed -e 's,.*/\(.*\),\1,') 54 | 55 | # Strip "v" prefix from tag name 56 | [[ "${{ github.ref }}" == "refs/tags/"* ]] && VERSION=$(echo $VERSION | sed -e 's/^v//') 57 | 58 | # Use Docker `latest` tag convention 59 | [ "$VERSION" == "master" ] && LATEST="latest" 60 | 61 | echo "OWNER=$OWNER" >> $GITHUB_ENV 62 | echo "VERSION=$VERSION" >> $GITHUB_ENV 63 | 64 | echo "OWNER=$OWNER" 65 | echo "VERSION=$VERSION" 66 | 67 | - 68 | name: Build container image 69 | uses: docker/build-push-action@v2 70 | with: 71 | context : ./docker/Arkime 72 | file : ./docker/Arkime/Arkime.dockerfile 73 | push: true 74 | tags: | 75 | ghcr.io/${{ env.OWNER }}/arkimeviewer:${{ github.sha }} 76 | ghcr.io/${{ env.OWNER }}/arkimeviewer:${{ env.VERSION }} 77 | cache-from: type=local,src=/tmp/.buildx-cache 78 | cache-to: type=local,dest=/tmp/.buildx-cache-new,mode=max 79 | 80 | - 81 | # Temp fix 82 | # https://github.com/docker/build-push-action/blob/master/docs/advanced/cache.md#github-cache 83 | # https://github.com/docker/build-push-action/issues/252 84 | # https://github.com/moby/buildkit/issues/1896 85 | name: Move cache 86 | run: | 87 | rm -rf /tmp/.buildx-cache 88 | mv /tmp/.buildx-cache-new /tmp/.buildx-cache -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | Stamus-Live-Build 3 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | ===== 2 | SELKS 3 | ===== 4 | 5 | Intro 6 | ===== 7 | 8 | SELKS is a free and open source Debian-based IDS/IPS/Network Security Monitoring platform 9 | released under GPLv3 from Stamus Networks (https://www.stamus-networks.com/). 10 | 11 | SELKS can be installed via docker compose on any Linux or Windows OS. Once installed it is 12 | ready to use out of the box solution. 13 | 14 | SELKS ISOs are also available for air gapped environment or bare metal or VM installation. 15 | 16 | 17 | .. image:: doc/images/Hunt-Filtersets-1.png 18 | :alt: SELKS 7 19 | :align: center 20 | 21 | SELKS is comprised of the following major components: 22 | 23 | * S - Suricata IDPS/NSM - https://suricata.io/ 24 | * E - Elasticsearch - https://www.elastic.co/products/elasticsearch 25 | * L - Logstash - https://www.elastic.co/products/logstash 26 | * K - Kibana - https://www.elastic.co/products/kibana 27 | * S - Scirius - https://github.com/StamusNetworks/scirius 28 | * EveBox - https://evebox.org/ 29 | * Arkime - https://arkime.com/ 30 | * CyberChef - https://github.com/gchq/CyberChef 31 | 32 | The acronym was established before the addition of Arkime, EveBox and CyberChef. 33 | 34 | And it includes preconfigured dashboards like this one: 35 | 36 | .. image:: doc/images/Overview-1.png 37 | :alt: Example view 38 | :align: center 39 | 40 | What is SELKS 41 | ============= 42 | 43 | Suricata 44 | -------- 45 | 46 | SELKS is a showcase of what Suricata IDS/IPS/NSM can do and the network protocol monitoring logs and alerts it produces. As such any and all data in SELKS is generated by Suricata: 47 | 48 | .. image:: doc/images/Suricata-Generated-Eventsv2-source.webp 49 | :alt: Suricata 50 | :align: center 51 | 52 | Threat Hunting 53 | -------------- 54 | 55 | The usage of Suricata data is further enhanced by Stamus' developed Scirius, a threat hunting interface. The interface is specifically designed for Suricata events and combines a drill down approach to pivot for quick exploration of alerts and NSM events. It includes predefined hunting filters and enhanced contextual views: 56 | 57 | .. image:: doc/images/Hunt-context-1.png 58 | :alt: Stamus 59 | :align: center 60 | 61 | .. image:: doc/images/Hunt-Context-2.png 62 | :alt: Stamus 63 | :align: center 64 | 65 | Logs 66 | ---- 67 | 68 | An example subset (not complete) of raw JSON logs generated by Suricata `can be found here <https://github.com/StamusNetworks/SELKS/tree/master/doc/example-logs>`_. 69 | 70 | Information 71 | ----------- 72 | 73 | If you are a new to Suricata, you can read a series of articles we wrote about `The other side of Suricata <https://www.stamus-networks.com/blog/the-other-side-of-suricata>`_. 74 | 75 | Dashboards 76 | ---------- 77 | 78 | SELKS has by default over 28 default dashboards, more than 400 visualizations and 24 predefined searches available. 79 | 80 | Here is an extract of the dashboards list: SN-ALERTS, SN-ALL, SN-ANOMALY, SN-DHCP, SN-DNS, SN-DNP3, SN-FILE-Transactions, SN-FLOW, SN-HTTP, SN-HUNT-1, SN-IDS, SN-IKEv2, SN-KRB5, SN-MQTT, SN-NFS, SN-OVERVIEW, SN-RDP, SN-RFB, SN-SANS-MTA-Training, SN-SIP, SN-SMB, SN-SMTP, SN-SNMP, SN-SSH, SN-STATS, SN-TLS, SN-VLAN, SN-TFTP, SN-TrafficID 81 | 82 | Additional visualizations and dashboards are also available in the ``Events viewer`` (EveBox). 83 | 84 | Getting SELKS 85 | ============= 86 | 87 | Prerequisites 88 | ------------- 89 | 90 | The minimal configuration for production usage is 2 cores and 9 Gb of memory. As Suricata 91 | and Elastisearch are multithreaded, the more cores you have the better it is. 92 | Regarding memory, the more traffic to monitor you have, the more getting some extra memory will be interesting. 93 | 94 | Docker 95 | ------ 96 | 97 | You can spin up SELKS on any Linux or Windows OSes in minutes via docker compose. See `Docker Installation <https://github.com/StamusNetworks/SELKS/wiki/Docker>`_. 98 | 99 | ISO 100 | --- 101 | 102 | For air gapped environement or full OS installation, see `SELKS ISO Setup <https://github.com/StamusNetworks/SELKS/wiki/Docker-ISO-setup>`_. 103 | 104 | Usage and logon credentials 105 | =========================== 106 | 107 | You need to authenticate to access to the web interface(see the ``HTTPS access`` section below ). The default user/password is ``selks-user/selks-user`` (including through the Dashboards or Scirius desktop icons). 108 | You can change credentials and user settings by using the top left menu in Scirius. 109 | 110 | For the ISO users 111 | ----------------- 112 | 113 | Default OS user: 114 | 115 | * user: ``selks-user`` 116 | * password: ``selks-user`` (password in Live mode is ``live``) 117 | 118 | The default root password is ``StamusNetworks`` 119 | 120 | HTTPS access 121 | ============ 122 | 123 | If you wish to remotely (from a different PC on your network) access the 124 | dashboards you could do that as follows (in your browser): 125 | 126 | * https://your.selks.IP.here/ - Scirius ruleset management and a central point for all dashboards and EveBox 127 | 128 | You need to authenticate to access to the web interface. The default user/password is the 129 | same as for local access: ``selks-user/selks-user``. Don't forget to change credentials at first 130 | login. You can do that by going to ``Account settings`` in the top left dropdown menu of 131 | Scirius. 132 | 133 | Getting help 134 | ============ 135 | 136 | You can get more information on SELKS wiki: https://github.com/StamusNetworks/SELKS/wiki 137 | 138 | You can get help about SELKS on our Discord channel https://discord.gg/h5mEdCewvn 139 | 140 | If you encounter a problem, you can open a ticket on https://github.com/StamusNetworks/SELKS/issues 141 | 142 | Enterprise scale Deployments 143 | ============================ 144 | 145 | While SELKS is suitable as a production network security solution in small to medium sized organizations and is a great system to test out the power of Suricata for intrusion detection and threat hunting, it was never designed to be deployed in an enterprise setting. For enterprise applications, please review our commercial solution, Stamus Security Platform (SSP). 146 | 147 | Stamus Security Platform (Commercial Solution) 148 | ============================================== 149 | Stamus Security Platform (SSP) is the commercial network-based threat detection and response solution from Stamus Networks. While it retains much of the same look and feel as SELKS, SSP is a completely different system and requires a new software installation. 150 | 151 | Available in two license tiers, SSP delivers: 152 | 153 | Broad-Spectrum Threat Detection 154 | ------------------------------- 155 | * Multiple detection mechanisms from machine learning, anomaly detection, and signatures 156 | * High-fidelity “Declarations of Compromise” with multi-stage attack timeline 157 | * Weekly threat intelligence updates from Stamus Labs 158 | 159 | Guided Threat Hunting and Incident Investigation 160 | ------------------------------------------------ 161 | * Advanced guided threat hunting filters 162 | * Host insights tracks over 60 security-related attributes 163 | * Easily convert hunt results into custom detection logic 164 | * Explainable and transparent results with evidence 165 | 166 | Enterprise Scale Management and Integration 167 | ------------------------------------------- 168 | * Automated classification and alert triage 169 | * Management of multiple probes from single console 170 | * Seamless integration with SOAR, SIEM, XDR, EDR, IR 171 | * Multi-tenant operation 172 | * Configuration backup and restoration 173 | 174 | 175 | More Information about SSP 176 | ========================== 177 | 178 | Visit `this page to request a demo of SSP <https://www.stamus-networks.com/demo>`_ 179 | 180 | To learn more about the differences between SELKS and our commercial solutions, please read through "*Understanding SELKS and Stamus Commercial Platforms*" `Download the white paper here. <https://www.stamus-networks.com/hubfs/Library/Documents%20(PDFs)/StamusNetworks-WP-SELKS-SSP-092021-1.pdf>`_ 181 | 182 | 183 | -------------------------------------------------------------------------------- /doc/example-logs/eve-anomaly.json: -------------------------------------------------------------------------------- 1 | { 2 | "_index": "logstash-anomaly-2021.10.08", 3 | "_type": "_doc", 4 | "_id": "CmJJX3wBJJ91CIEeBZcp", 5 | "_score": 1, 6 | "_source": { 7 | "in_iface": "tppdummy0", 8 | "timestamp": "2021-10-08T12:43:12.368145+0300", 9 | "anomaly": { 10 | "event": "APPLAYER_WRONG_DIRECTION_FIRST_DATA", 11 | "type": "applayer", 12 | "layer": "proto_detect" 13 | }, 14 | "dest_ip": "172.16.1.101", 15 | "src_port": 443, 16 | "@timestamp": "2021-10-08T09:43:12.368Z", 17 | "flow_id": 225073769458405, 18 | "host": "SELKS", 19 | "event_type": "anomaly", 20 | "path": "/var/log/suricata/eve.json", 21 | "geoip": { 22 | "city_name": "Sofia", 23 | "latitude": 42.6951, 24 | "country_name": "Bulgaria", 25 | "postal_code": "1000", 26 | "timezone": "Europe/Sofia", 27 | "country_code3": "BG", 28 | "ip": "88.80.148.177", 29 | "country_code2": "BG", 30 | "region_code": "22", 31 | "continent_code": "EU", 32 | "location": { 33 | "lon": 23.325, 34 | "lat": 42.6951 35 | }, 36 | "longitude": 23.325, 37 | "region_name": "Sofia-Capital" 38 | }, 39 | "tags": [ 40 | "_geoip_lookup_failure" 41 | ], 42 | "community_id": "1:OLl/QygtCj1zuydnzQrXdjhRwsU=", 43 | "type": "SELKS", 44 | "@version": "1", 45 | "proto": "TCP", 46 | "src_ip": "88.80.148.177", 47 | "dest_port": 49935 48 | }, 49 | "fields": { 50 | "geoip.timezone": [ 51 | "Europe/Sofia" 52 | ], 53 | "anomaly.event": [ 54 | "APPLAYER_WRONG_DIRECTION_FIRST_DATA" 55 | ], 56 | "geoip.region_name.keyword": [ 57 | "Sofia-Capital" 58 | ], 59 | "geoip.country_code2.keyword": [ 60 | "BG" 61 | ], 62 | "geoip.country_name.keyword": [ 63 | "Bulgaria" 64 | ], 65 | "type": [ 66 | "SELKS" 67 | ], 68 | "path": [ 69 | "/var/log/suricata/eve.json" 70 | ], 71 | "event_type": [ 72 | "anomaly" 73 | ], 74 | "geoip.region_code.keyword": [ 75 | "22" 76 | ], 77 | "proto.keyword": [ 78 | "TCP" 79 | ], 80 | "flow_id": [ 81 | 225073769458405 82 | ], 83 | "type.keyword": [ 84 | "SELKS" 85 | ], 86 | "host": [ 87 | "SELKS" 88 | ], 89 | "geoip.city_name.keyword": [ 90 | "Sofia" 91 | ], 92 | "EveBox": [ 93 | 225073769458405 94 | ], 95 | "geoip.longitude": [ 96 | 23.328125 97 | ], 98 | "host.keyword": [ 99 | "SELKS" 100 | ], 101 | "dest_port": [ 102 | 49935 103 | ], 104 | "anomaly.layer.keyword": [ 105 | "proto_detect" 106 | ], 107 | "geoip.region_name": [ 108 | "Sofia-Capital" 109 | ], 110 | "tags": [ 111 | "_geoip_lookup_failure" 112 | ], 113 | "geoip.continent_code.keyword": [ 114 | "EU" 115 | ], 116 | "dest_ip.keyword": [ 117 | "172.16.1.101" 118 | ], 119 | "anomaly.type.keyword": [ 120 | "applayer" 121 | ], 122 | "dest_ip": [ 123 | "172.16.1.101" 124 | ], 125 | "proto": [ 126 | "TCP" 127 | ], 128 | "FPC": [ 129 | "ip == 88.80.148.177 && port == 443 && ip == 172.16.1.101 && port == 49935 && protocols == tcp" 130 | ], 131 | "geoip.latitude": [ 132 | 42.6875 133 | ], 134 | "geoip.continent_code": [ 135 | "EU" 136 | ], 137 | "geoip.postal_code.keyword": [ 138 | "1000" 139 | ], 140 | "geoip.region_code": [ 141 | "22" 142 | ], 143 | "tags.keyword": [ 144 | "_geoip_lookup_failure" 145 | ], 146 | "geoip.country_code3.keyword": [ 147 | "BG" 148 | ], 149 | "event_type.keyword": [ 150 | "anomaly" 151 | ], 152 | "geoip.ip": [ 153 | "88.80.148.177" 154 | ], 155 | "in_iface.keyword": [ 156 | "tppdummy0" 157 | ], 158 | "src_ip": [ 159 | "88.80.148.177" 160 | ], 161 | "community_id": [ 162 | "1:OLl/QygtCj1zuydnzQrXdjhRwsU=" 163 | ], 164 | "geoip.country_code3": [ 165 | "BG" 166 | ], 167 | "geoip.location": [ 168 | { 169 | "coordinates": [ 170 | 23.325, 171 | 42.6951 172 | ], 173 | "type": "Point" 174 | } 175 | ], 176 | "geoip.country_code2": [ 177 | "BG" 178 | ], 179 | "anomaly.event.keyword": [ 180 | "APPLAYER_WRONG_DIRECTION_FIRST_DATA" 181 | ], 182 | "@version": [ 183 | "1" 184 | ], 185 | "geoip.country_name": [ 186 | "Bulgaria" 187 | ], 188 | "src_ip.keyword": [ 189 | "88.80.148.177" 190 | ], 191 | "timestamp": [ 192 | "2021-10-08T09:43:12.368Z" 193 | ], 194 | "anomaly.layer": [ 195 | "proto_detect" 196 | ], 197 | "community_id.keyword": [ 198 | "1:OLl/QygtCj1zuydnzQrXdjhRwsU=" 199 | ], 200 | "geoip.city_name": [ 201 | "Sofia" 202 | ], 203 | "in_iface": [ 204 | "tppdummy0" 205 | ], 206 | "geoip.postal_code": [ 207 | "1000" 208 | ], 209 | "src_port": [ 210 | 443 211 | ], 212 | "@timestamp": [ 213 | "2021-10-08T09:43:12.368Z" 214 | ], 215 | "geoip.timezone.keyword": [ 216 | "Europe/Sofia" 217 | ], 218 | "anomaly.type": [ 219 | "applayer" 220 | ], 221 | "path.keyword": [ 222 | "/var/log/suricata/eve.json" 223 | ] 224 | } 225 | } 226 | -------------------------------------------------------------------------------- /doc/example-logs/eve-fileinfo.json: -------------------------------------------------------------------------------- 1 | { 2 | "in_iface": "tppdummy0", 3 | "timestamp": "2021-10-08T12:40:00.965786+0300", 4 | "fileinfo": { 5 | "sid": [], 6 | "stored": false, 7 | "magic": "PE32+ executable (DLL) (GUI) x86-64, for MS Windows", 8 | "state": "CLOSED", 9 | "size": 186336, 10 | "type": "PE32+ executable (DLL) (GUI) x86-64", 11 | "filename": "/177v2.dll", 12 | "tx_id": 0, 13 | "sha1": "173e0de913fa275e3ef31f394b9479a0a1eabaee", 14 | "sha256": "2bfe11c06ffe157399432080f6de6190e1062c99b4a55ec31974b5a37ee8dd3c", 15 | "md5": "41c9aa93d70b7a5238a262f6e3971415", 16 | "gaps": false 17 | }, 18 | "dest_ip": "172.16.1.101", 19 | "src_port": 80, 20 | "http": { 21 | "http_content_type": "application/x-msdos-program", 22 | "http_method": "GET", 23 | "protocol": "HTTP/1.1", 24 | "length": 186336, 25 | "hostname": "82.118.21.221", 26 | "url": "/177v2.dll", 27 | "http_user_agent": "curl/7.74.0", 28 | "status": 200, 29 | "user_agent": { 30 | "device": "Other", 31 | "os_name": "Other", 32 | "os": "Other", 33 | "version": "7.74.0", 34 | "minor": "74", 35 | "patch": "0", 36 | "os_full": "Other", 37 | "major": "7", 38 | "name": "curl" 39 | } 40 | }, 41 | "@timestamp": "2021-10-08T09:40:00.965Z", 42 | "flow_id": 1357003807701027, 43 | "metadata": { 44 | "flowbits": [ 45 | "http.dottedquadhost.dll", 46 | "ET.http.binary" 47 | ] 48 | }, 49 | "event_type": "fileinfo", 50 | "host": "SELKS", 51 | "path": "/var/log/suricata/eve.json", 52 | "geoip": { 53 | "city_name": "Gdansk", 54 | "latitude": 54.3601, 55 | "country_name": "Poland", 56 | "postal_code": "80-860", 57 | "timezone": "Europe/Warsaw", 58 | "country_code3": "PL", 59 | "ip": "82.118.21.221", 60 | "country_code2": "PL", 61 | "region_code": "22", 62 | "continent_code": "EU", 63 | "location": { 64 | "lon": 18.664, 65 | "lat": 54.3601 66 | }, 67 | "longitude": 18.664, 68 | "region_name": "Pomerania" 69 | }, 70 | "app_proto": "http", 71 | "tags": [ 72 | "_geoip_lookup_failure" 73 | ], 74 | "community_id": "1:oQpfk+DMURhDz3k1FILE0ZFmIvc=", 75 | "type": "SELKS", 76 | "@version": "1", 77 | "proto": "TCP", 78 | "src_ip": "82.118.21.221", 79 | "dest_port": 49900 80 | } 81 | -------------------------------------------------------------------------------- /doc/example-logs/eve-flow.json: -------------------------------------------------------------------------------- 1 | { 2 | "in_iface": "tppdummy0", 3 | "timestamp": "2021-10-08T12:43:23.016383+0300", 4 | "dest_ip": "82.118.21.221", 5 | "src_port": 49900, 6 | "tcp": { 7 | "state": "closed", 8 | "psh": true, 9 | "tcp_flags_tc": "1b", 10 | "fin": true, 11 | "ack": true, 12 | "syn": true, 13 | "tcp_flags": "1b", 14 | "tcp_flags_ts": "1b" 15 | }, 16 | "@timestamp": "2021-10-08T09:43:23.016Z", 17 | "flow_id": 1357003807701027, 18 | "metadata": { 19 | "flowbits": [ 20 | "http.dottedquadhost.dll", 21 | "ET.http.binary" 22 | ] 23 | }, 24 | "event_type": "flow", 25 | "host": "SELKS", 26 | "path": "/var/log/suricata/eve.json", 27 | "geoip": { 28 | "city_name": "Gdansk", 29 | "latitude": 54.3601, 30 | "country_name": "Poland", 31 | "postal_code": "80-860", 32 | "timezone": "Europe/Warsaw", 33 | "country_code3": "PL", 34 | "ip": "82.118.21.221", 35 | "country_code2": "PL", 36 | "region_code": "22", 37 | "continent_code": "EU", 38 | "location": { 39 | "lon": 18.664, 40 | "lat": 54.3601 41 | }, 42 | "longitude": 18.664, 43 | "region_name": "Pomerania" 44 | }, 45 | "app_proto": "http", 46 | "tags": [ 47 | "_geoip_lookup_failure" 48 | ], 49 | "community_id": "1:oQpfk+DMURhDz3k1FILE0ZFmIvc=", 50 | "flow": { 51 | "age": 19, 52 | "reason": "unknown", 53 | "state": "closed", 54 | "alerted": true, 55 | "pkts_toserver": 46, 56 | "pkts_toclient": 140, 57 | "start": "2021-10-08T12:39:54.899107+0300", 58 | "end": "2021-10-08T12:40:13.032461+0300", 59 | "bytes_toserver": 2593, 60 | "bytes_toclient": 194216 61 | }, 62 | "type": "SELKS", 63 | "@version": "1", 64 | "proto": "TCP", 65 | "src_ip": "172.16.1.101", 66 | "dest_port": 80 67 | } 68 | -------------------------------------------------------------------------------- /doc/example-logs/eve-http.json: -------------------------------------------------------------------------------- 1 | { 2 | "in_iface": "tppdummy0", 3 | "timestamp": "2021-10-08T12:40:00.965786+0300", 4 | "dest_ip": "82.118.21.221", 5 | "src_port": 49900, 6 | "http": { 7 | "server": "Apache/2.4.25 (Debian)", 8 | "connection": "Keep-Alive", 9 | "length": 186336, 10 | "response_headers": [ 11 | { 12 | "value": "Thu, 15 Jul 2021 17:35:16 GMT", 13 | "name": "Date" 14 | }, 15 | { 16 | "value": "Apache/2.4.25 (Debian)", 17 | "name": "Server" 18 | }, 19 | { 20 | "value": "Thu, 15 Jul 2021 17:23:21 GMT", 21 | "name": "Last-Modified" 22 | }, 23 | { 24 | "value": "\"2d7e0-5c72cba5015f9\"", 25 | "name": "ETag" 26 | }, 27 | { 28 | "value": "bytes", 29 | "name": "Accept-Ranges" 30 | }, 31 | { 32 | "value": "186336", 33 | "name": "Content-Length" 34 | }, 35 | { 36 | "value": "timeout=5, max=100", 37 | "name": "Keep-Alive" 38 | }, 39 | { 40 | "value": "Keep-Alive", 41 | "name": "Connection" 42 | }, 43 | { 44 | "value": "application/x-msdos-program", 45 | "name": "Content-Type" 46 | } 47 | ], 48 | "status": 200, 49 | "http_user_agent": "curl/7.74.0", 50 | "user_agent": { 51 | "device": "Other", 52 | "os_name": "Other", 53 | "os": "Other", 54 | "version": "7.74.0", 55 | "minor": "74", 56 | "patch": "0", 57 | "os_full": "Other", 58 | "major": "7", 59 | "name": "curl" 60 | }, 61 | "date": "Thu, 15 Jul 2021 17:35:16 GMT", 62 | "last_modified": "Thu, 15 Jul 2021 17:23:21 GMT", 63 | "http_content_type": "application/x-msdos-program", 64 | "http_method": "GET", 65 | "protocol": "HTTP/1.1", 66 | "content_type": "application/x-msdos-program", 67 | "hostname": "82.118.21.221", 68 | "url": "/177v2.dll", 69 | "request_headers": [ 70 | { 71 | "value": "Keep-Alive", 72 | "name": "Connection" 73 | }, 74 | { 75 | "value": "curl/7.74.0", 76 | "name": "User-Agent" 77 | }, 78 | { 79 | "value": "82.118.21.221", 80 | "name": "Host" 81 | } 82 | ], 83 | "content_length": "186336" 84 | }, 85 | "@timestamp": "2021-10-08T09:40:00.965Z", 86 | "flow_id": 1357003807701027, 87 | "metadata": { 88 | "flowbits": [ 89 | "http.dottedquadhost.dll", 90 | "ET.http.binary" 91 | ] 92 | }, 93 | "event_type": "http", 94 | "host": "SELKS", 95 | "path": "/var/log/suricata/eve.json", 96 | "geoip": { 97 | "city_name": "Gdansk", 98 | "latitude": 54.3601, 99 | "country_name": "Poland", 100 | "postal_code": "80-860", 101 | "timezone": "Europe/Warsaw", 102 | "country_code3": "PL", 103 | "ip": "82.118.21.221", 104 | "country_code2": "PL", 105 | "region_code": "22", 106 | "continent_code": "EU", 107 | "location": { 108 | "lon": 18.664, 109 | "lat": 54.3601 110 | }, 111 | "longitude": 18.664, 112 | "region_name": "Pomerania" 113 | }, 114 | "tags": [ 115 | "_geoip_lookup_failure" 116 | ], 117 | "community_id": "1:oQpfk+DMURhDz3k1FILE0ZFmIvc=", 118 | "type": "SELKS", 119 | "tx_id": 0, 120 | "proto": "TCP", 121 | "src_ip": "172.16.1.101", 122 | "dest_port": 80, 123 | "@version": "1" 124 | } 125 | -------------------------------------------------------------------------------- /doc/example-logs/eve-krb5.json: -------------------------------------------------------------------------------- 1 | { 2 | "_index": "logstash-krb5-2021.10.08", 3 | "_type": "_doc", 4 | "_id": "DWJBX3wBJJ91CIEeFpGR", 5 | "_score": 1, 6 | "_source": { 7 | "in_iface": "tppdummy0", 8 | "timestamp": "2021-10-08T12:34:33.365773+0300", 9 | "dest_ip": "172.16.1.6", 10 | "src_port": 49712, 11 | "@timestamp": "2021-10-08T09:34:33.365Z", 12 | "flow_id": 489587896581810, 13 | "host": "SELKS", 14 | "event_type": "krb5", 15 | "path": "/var/log/suricata/eve.json", 16 | "geoip": {}, 17 | "tags": [ 18 | "_geoip_lookup_failure" 19 | ], 20 | "community_id": "1:++UEkFDHjpG/jMRZZelNxleEZ7Q=", 21 | "type": "SELKS", 22 | "krb5": { 23 | "cname": "DEKSTOP-D9UMVWL$", 24 | "msg_type": "KRB_TGS_REP", 25 | "sname": "dekstop-d9umvwl$", 26 | "encryption": "aes256-cts-hmac-sha1-96", 27 | "realm": "SIMONSAYSGO.NET", 28 | "weak_encryption": false 29 | }, 30 | "proto": "TCP", 31 | "src_ip": "172.16.1.101", 32 | "dest_port": 88, 33 | "@version": "1" 34 | }, 35 | "fields": { 36 | "krb5.sname.keyword": [ 37 | "dekstop-d9umvwl$" 38 | ], 39 | "krb5.msg_type": [ 40 | "KRB_TGS_REP" 41 | ], 42 | "tags.keyword": [ 43 | "_geoip_lookup_failure" 44 | ], 45 | "krb5.realm.keyword": [ 46 | "SIMONSAYSGO.NET" 47 | ], 48 | "event_type.keyword": [ 49 | "krb5" 50 | ], 51 | "type": [ 52 | "SELKS" 53 | ], 54 | "krb5.encryption.keyword": [ 55 | "aes256-cts-hmac-sha1-96" 56 | ], 57 | "in_iface.keyword": [ 58 | "tppdummy0" 59 | ], 60 | "src_ip": [ 61 | "172.16.1.101" 62 | ], 63 | "path": [ 64 | "/var/log/suricata/eve.json" 65 | ], 66 | "community_id": [ 67 | "1:++UEkFDHjpG/jMRZZelNxleEZ7Q=" 68 | ], 69 | "event_type": [ 70 | "krb5" 71 | ], 72 | "krb5.cname": [ 73 | "DEKSTOP-D9UMVWL$" 74 | ], 75 | "proto.keyword": [ 76 | "TCP" 77 | ], 78 | "flow_id": [ 79 | 489587896581810 80 | ], 81 | "type.keyword": [ 82 | "SELKS" 83 | ], 84 | "host": [ 85 | "SELKS" 86 | ], 87 | "@version": [ 88 | "1" 89 | ], 90 | "krb5.sname": [ 91 | "dekstop-d9umvwl$" 92 | ], 93 | "EveBox": [ 94 | 489587896581810 95 | ], 96 | "src_ip.keyword": [ 97 | "172.16.1.101" 98 | ], 99 | "host.keyword": [ 100 | "SELKS" 101 | ], 102 | "dest_port": [ 103 | 88 104 | ], 105 | "timestamp": [ 106 | "2021-10-08T09:34:33.365Z" 107 | ], 108 | "krb5.weak_encryption": [ 109 | false 110 | ], 111 | "krb5.cname.keyword": [ 112 | "DEKSTOP-D9UMVWL$" 113 | ], 114 | "krb5.realm": [ 115 | "SIMONSAYSGO.NET" 116 | ], 117 | "community_id.keyword": [ 118 | "1:++UEkFDHjpG/jMRZZelNxleEZ7Q=" 119 | ], 120 | "tags": [ 121 | "_geoip_lookup_failure" 122 | ], 123 | "krb5.encryption": [ 124 | "aes256-cts-hmac-sha1-96" 125 | ], 126 | "in_iface": [ 127 | "tppdummy0" 128 | ], 129 | "src_port": [ 130 | 49712 131 | ], 132 | "@timestamp": [ 133 | "2021-10-08T09:34:33.365Z" 134 | ], 135 | "dest_ip.keyword": [ 136 | "172.16.1.6" 137 | ], 138 | "dest_ip": [ 139 | "172.16.1.6" 140 | ], 141 | "proto": [ 142 | "TCP" 143 | ], 144 | "FPC": [ 145 | "ip == 172.16.1.101 && port == 49712 && ip == 172.16.1.6 && port == 88 && protocols == tcp" 146 | ], 147 | "krb5.msg_type.keyword": [ 148 | "KRB_TGS_REP" 149 | ], 150 | "path.keyword": [ 151 | "/var/log/suricata/eve.json" 152 | ] 153 | } 154 | } 155 | -------------------------------------------------------------------------------- /doc/example-logs/eve-smb.json: -------------------------------------------------------------------------------- 1 | { 2 | "_index": "logstash-smb-2021.10.08", 3 | "_type": "_doc", 4 | "_id": "8mJJX3wBJJ91CIEeAZY1", 5 | "_score": 1, 6 | "_source": { 7 | "in_iface": "tppdummy0", 8 | "timestamp": "2021-10-08T12:43:11.765772+0300", 9 | "dest_ip": "172.16.1.6", 10 | "src_port": 50143, 11 | "@timestamp": "2021-10-08T09:43:11.765Z", 12 | "flow_id": 2065241780228204, 13 | "host": "SELKS", 14 | "event_type": "smb", 15 | "path": "/var/log/suricata/eve.json", 16 | "geoip": {}, 17 | "smb": { 18 | "status_code": "0x0", 19 | "dialect": "3.11", 20 | "share_type": "FILE", 21 | "tree_id": 1, 22 | "id": 4, 23 | "command": "SMB2_COMMAND_TREE_CONNECT", 24 | "status": "STATUS_SUCCESS", 25 | "share": "\\\\SimonSaysGo-DC.simonsaysgo.net\\sysvol", 26 | "session_id": 255087100297233 27 | }, 28 | "tags": [ 29 | "_geoip_lookup_failure" 30 | ], 31 | "community_id": "1:LPRuBxoltIaeqqgwde6ktefkpmU=", 32 | "type": "SELKS", 33 | "@version": "1", 34 | "proto": "TCP", 35 | "src_ip": "172.16.1.101", 36 | "dest_port": 445 37 | }, 38 | "fields": { 39 | "tags.keyword": [ 40 | "_geoip_lookup_failure" 41 | ], 42 | "event_type.keyword": [ 43 | "smb" 44 | ], 45 | "type": [ 46 | "SELKS" 47 | ], 48 | "smb.dialect.keyword": [ 49 | "3.11" 50 | ], 51 | "in_iface.keyword": [ 52 | "tppdummy0" 53 | ], 54 | "smb.dialect": [ 55 | "3.11" 56 | ], 57 | "src_ip": [ 58 | "172.16.1.101" 59 | ], 60 | "path": [ 61 | "/var/log/suricata/eve.json" 62 | ], 63 | "smb.command.keyword": [ 64 | "SMB2_COMMAND_TREE_CONNECT" 65 | ], 66 | "community_id": [ 67 | "1:LPRuBxoltIaeqqgwde6ktefkpmU=" 68 | ], 69 | "event_type": [ 70 | "smb" 71 | ], 72 | "proto.keyword": [ 73 | "TCP" 74 | ], 75 | "flow_id": [ 76 | 2065241780228204 77 | ], 78 | "type.keyword": [ 79 | "SELKS" 80 | ], 81 | "smb.status.keyword": [ 82 | "STATUS_SUCCESS" 83 | ], 84 | "smb.session_id": [ 85 | 255087100297233 86 | ], 87 | "host": [ 88 | "SELKS" 89 | ], 90 | "smb.status": [ 91 | "STATUS_SUCCESS" 92 | ], 93 | "@version": [ 94 | "1" 95 | ], 96 | "smb.status_code": [ 97 | "0x0" 98 | ], 99 | "smb.status_code.keyword": [ 100 | "0x0" 101 | ], 102 | "EveBox": [ 103 | 2065241780228204 104 | ], 105 | "src_ip.keyword": [ 106 | "172.16.1.101" 107 | ], 108 | "host.keyword": [ 109 | "SELKS" 110 | ], 111 | "dest_port": [ 112 | 445 113 | ], 114 | "timestamp": [ 115 | "2021-10-08T09:43:11.765Z" 116 | ], 117 | "smb.share.keyword": [ 118 | "\\\\SimonSaysGo-DC.simonsaysgo.net\\sysvol" 119 | ], 120 | "community_id.keyword": [ 121 | "1:LPRuBxoltIaeqqgwde6ktefkpmU=" 122 | ], 123 | "smb.command": [ 124 | "SMB2_COMMAND_TREE_CONNECT" 125 | ], 126 | "smb.id": [ 127 | 4 128 | ], 129 | "tags": [ 130 | "_geoip_lookup_failure" 131 | ], 132 | "in_iface": [ 133 | "tppdummy0" 134 | ], 135 | "src_port": [ 136 | 50143 137 | ], 138 | "smb.share_type": [ 139 | "FILE" 140 | ], 141 | "@timestamp": [ 142 | "2021-10-08T09:43:11.765Z" 143 | ], 144 | "dest_ip.keyword": [ 145 | "172.16.1.6" 146 | ], 147 | "smb.tree_id": [ 148 | 1 149 | ], 150 | "smb.share_type.keyword": [ 151 | "FILE" 152 | ], 153 | "dest_ip": [ 154 | "172.16.1.6" 155 | ], 156 | "proto": [ 157 | "TCP" 158 | ], 159 | "FPC": [ 160 | "ip == 172.16.1.101 && port == 50143 && ip == 172.16.1.6 && port == 445 && protocols == tcp" 161 | ], 162 | "smb.share": [ 163 | "\\\\SimonSaysGo-DC.simonsaysgo.net\\sysvol" 164 | ], 165 | "path.keyword": [ 166 | "/var/log/suricata/eve.json" 167 | ] 168 | } 169 | } 170 | -------------------------------------------------------------------------------- /doc/example-logs/eve-tls.json: -------------------------------------------------------------------------------- 1 | { 2 | "in_iface": "tppdummy0", 3 | "timestamp": "2021-10-08T12:44:32.732441+0300", 4 | "dest_ip": "181.114.215.239", 5 | "src_port": 50229, 6 | "@timestamp": "2021-10-08T09:44:32.732Z", 7 | "flow_id": 712904760397913, 8 | "metadata": { 9 | "flowbits": [ 10 | "ET.meterpreter.ja3" 11 | ] 12 | }, 13 | "event_type": "tls", 14 | "host": "SELKS", 15 | "path": "/var/log/suricata/eve.json", 16 | "geoip": { 17 | "city_name": "Intendente Alvear", 18 | "latitude": -35.2357, 19 | "country_name": "Argentina", 20 | "postal_code": "6221", 21 | "timezone": "America/Argentina/Salta", 22 | "country_code3": "AR", 23 | "ip": "181.114.215.239", 24 | "country_code2": "AR", 25 | "region_code": "L", 26 | "continent_code": "SA", 27 | "location": { 28 | "lon": -63.5904, 29 | "lat": -35.2357 30 | }, 31 | "longitude": -63.5904, 32 | "region_name": "La Pampa" 33 | }, 34 | "tags": [ 35 | "_geoip_lookup_failure" 36 | ], 37 | "community_id": "1:k1oYipjAZggIhOaUV+okxGffO+4=", 38 | "tls": { 39 | "fingerprint": "e7:74:3f:c4:a4:88:dd:9b:b2:4f:fc:38:1d:ae:a9:a5:4b:c7:d1:da", 40 | "ja3s": { 41 | "hash": "0eec924176fb005dfa419c80ab72d27c", 42 | "string": "769,49172,65281-11-35-23" 43 | }, 44 | "notafter": "2022-06-21T19:10:50", 45 | "ja3": { 46 | "hash": "72a589da586844d7f0818ce684948eea", 47 | "string": "771,49196-49195-49200-49199-49188-49187-49192-49191-49162-49161-49172-49171-157-156-61-60-53-47-10,5-10-11-13-35-23-65281,29-23-24,0" 48 | }, 49 | "version": "TLSv1", 50 | "subject": "C=AU, ST=Some-State, O=Internet Widgits Pty Ltd", 51 | "serial": "00:CF:1D:44:E8:2D:24:88:04", 52 | "issuerdn": "C=AU, ST=Some-State, O=Internet Widgits Pty Ltd", 53 | "notbefore": "2021-06-21T19:10:50" 54 | }, 55 | "type": "SELKS", 56 | "@version": "1", 57 | "proto": "TCP", 58 | "src_ip": "172.16.1.101", 59 | "dest_port": 443 60 | } 61 | -------------------------------------------------------------------------------- /doc/images/Distro-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StamusNetworks/SELKS/4af455cd15f69f2ba471fa6cd0b96d6aae6e93b9/doc/images/Distro-1.png -------------------------------------------------------------------------------- /doc/images/Distro-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StamusNetworks/SELKS/4af455cd15f69f2ba471fa6cd0b96d6aae6e93b9/doc/images/Distro-2.png -------------------------------------------------------------------------------- /doc/images/Hunt-Context-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StamusNetworks/SELKS/4af455cd15f69f2ba471fa6cd0b96d6aae6e93b9/doc/images/Hunt-Context-2.png -------------------------------------------------------------------------------- /doc/images/Hunt-Filtersets-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StamusNetworks/SELKS/4af455cd15f69f2ba471fa6cd0b96d6aae6e93b9/doc/images/Hunt-Filtersets-1.png -------------------------------------------------------------------------------- /doc/images/Hunt-context-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StamusNetworks/SELKS/4af455cd15f69f2ba471fa6cd0b96d6aae6e93b9/doc/images/Hunt-context-1.png -------------------------------------------------------------------------------- /doc/images/Overview-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StamusNetworks/SELKS/4af455cd15f69f2ba471fa6cd0b96d6aae6e93b9/doc/images/Overview-1.png -------------------------------------------------------------------------------- /doc/images/Overview-KRB5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StamusNetworks/SELKS/4af455cd15f69f2ba471fa6cd0b96d6aae6e93b9/doc/images/Overview-KRB5.png -------------------------------------------------------------------------------- /doc/images/Overview-filetransactions.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StamusNetworks/SELKS/4af455cd15f69f2ba471fa6cd0b96d6aae6e93b9/doc/images/Overview-filetransactions.png -------------------------------------------------------------------------------- /doc/images/Supplemental-info.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StamusNetworks/SELKS/4af455cd15f69f2ba471fa6cd0b96d6aae6e93b9/doc/images/Supplemental-info.png -------------------------------------------------------------------------------- /doc/images/Suricata-Generated-Eventsv2-source.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StamusNetworks/SELKS/4af455cd15f69f2ba471fa6cd0b96d6aae6e93b9/doc/images/Suricata-Generated-Eventsv2-source.webp -------------------------------------------------------------------------------- /docker/Arkime/Arkime.dockerfile: -------------------------------------------------------------------------------- 1 | 2 | 3 | FROM debian:bullseye as installer 4 | 5 | # Declare args 6 | ARG ARKIME_VERSION=5.0.0 7 | ARG UBUNTU_VERSION=20.04 8 | ARG ARKIME_DEB_PACKAGE="arkime_"$ARKIME_VERSION"-1_amd64.deb" 9 | ARG ARKIMEDIR "/opt/arkime" 10 | 11 | ENV ARKIME_VERSION $ARKIME_VERSION 12 | ENV UBUNTU_VERSION $UBUNTU_VERSION 13 | ENV ARKIME_DEB_PACKAGE $ARKIME_DEB_PACKAGE 14 | ENV ARKIMEDIR "/opt/arkime" 15 | 16 | 17 | # Install Arkime 18 | RUN apt-get update && apt-get install -y curl wget logrotate 19 | RUN mkdir -p /tmp /suricata-logs 20 | 21 | WORKDIR /tmp 22 | RUN wget -q "https://s3.amazonaws.com/files.molo.ch/builds/ubuntu-"$UBUNTU_VERSION"/"$ARKIME_DEB_PACKAGE 23 | RUN apt-get install -y ./$ARKIME_DEB_PACKAGE 24 | 25 | RUN wget -q -O /opt/arkime/etc/oui.txt "https://www.wireshark.org/download/automated/data/manuf" 26 | RUN $ARKIMEDIR/bin/arkime_update_geo.sh 27 | 28 | 29 | # add config 30 | 31 | FROM debian:bullseye as runner 32 | 33 | # Declare args 34 | 35 | ENV ES_HOST "elasticsearch" 36 | ENV ES_PORT 9200 37 | ENV ARKIME_ADMIN_USERNAME "selks-user" 38 | ENV ARKIME_ADMIN_PASSWORD "selks-user" 39 | ENV ARKIME_HOSTNAME "arkime" 40 | ENV ARKIMEDIR "/opt/arkime" 41 | 42 | RUN apt-get update && apt-get install -y libpcre3 libyaml-0-2 libssl1.1 libmagic1 curl libwww-perl libjson-perl 43 | 44 | COPY --from=installer $ARKIMEDIR $ARKIMEDIR 45 | 46 | COPY start-arkimeviewer.sh /start-arkimeviewer.sh 47 | COPY arkimepcapread-selks-config.ini /opt/arkime/etc/config.ini 48 | 49 | RUN chmod 755 /start-arkimeviewer.sh && \ 50 | mkdir -p /readpcap 51 | 52 | EXPOSE 8005 53 | WORKDIR $ARKIMEDIR 54 | 55 | ENTRYPOINT [ "bash", "-c" ] 56 | CMD ["/start-arkimeviewer.sh"] 57 | -------------------------------------------------------------------------------- /docker/Arkime/start-arkimeviewer.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo "Using ES_HOST: $ES_HOST and ES_PORT: $ES_PORT" 3 | echo "Giving ES time to start..." 4 | until curl -sS "http://$ES_HOST:$ES_PORT/_cluster/health" 5 | do 6 | echo "Waiting for ES to start" 7 | sleep 3 8 | done 9 | 10 | echo 11 | echo "ES started..." 12 | 13 | until [[ -d "/suricata-logs/fpc" ]] && [[ -f "/suricata-logs/eve.json" ]] 14 | do 15 | echo "Waiting for Suricata to populate FPC and eve.json" 16 | sleep 3 17 | done 18 | 19 | # set runtime environment variables 20 | export ARKIME_ELASTICSEARCH="http://"$ES_HOST":"$ES_PORT 21 | 22 | if [ ! -f $ARKIMEDIR/etc/.initialized ]; then 23 | echo "Initializing ES database..." 24 | echo INIT | $ARKIMEDIR/db/db.pl $ARKIME_ELASTICSEARCH init 25 | $ARKIMEDIR/bin/arkime_add_user.sh $ARKIME_ADMIN_USERNAME "SELKS Admin User" $ARKIME_ADMIN_PASSWORD --admin 26 | $ARKIMEDIR/bin/arkime_add_user.sh moloch moloch moloch --admin --webauth 27 | echo $ARKIME_VERSION > $ARKIMEDIR/etc/.initialized 28 | echo UPGRADE | $ARKIMEDIR/db/db.pl http://$ES_HOST:$ES_PORT upgrade 29 | else 30 | echo "ES database already initialized..." 31 | # possible update 32 | read old_ver < $ARKIMEDIR/etc/.initialized 33 | # detect the newer version 34 | newer_ver=`echo -e "$old_ver\n$ARKIME_VERSION" | sort -rV | head -n 1` 35 | # the old version should not be the same as the newer version 36 | # otherwise -> upgrade 37 | if [ "$old_ver" != "$newer_ver" ]; then 38 | echo "Upgrading ES database..." 39 | echo UPGRADE | $ARKIMEDIR/db/db.pl http://$ES_HOST:$ES_PORT upgrade 40 | echo $ARKIME_VERSION > $ARKIMEDIR/etc/.initialized 41 | fi 42 | fi 43 | 44 | echo "Starting Arkime capture in the background..." 45 | exec $ARKIMEDIR/bin/capture -m -s -R /suricata-logs/fpc/ >> $ARKIMEDIR/logs/capture.log 2>&1 & 46 | 47 | echo "Look at log files for errors" 48 | echo " /data/logs/viewer.log" 49 | echo " /data/logs/capture.log" 50 | echo "Visit http://127.0.0.1:8005 with your favorite browser." 51 | echo " user: $ARKIME_ADMIN_USERNAME" 52 | echo " password: $ARKIME_ADMIN_PASSWORD" 53 | 54 | echo "Launch viewer..." 55 | cd $ARKIMEDIR/viewer 56 | $ARKIMEDIR/bin/node $ARKIMEDIR/viewer/viewer.js >> $ARKIMEDIR/logs/viewer.log 2>&1 -------------------------------------------------------------------------------- /docker/README.md: -------------------------------------------------------------------------------- 1 | SELKS on Docker 2 | =============== 3 | 4 | Intro 5 | ----- 6 | 7 | This version of SELKS is based on docker and intended to provide easier deployment and management. 8 | The installation procedure here is valid for any Linux OS that supports docker. 9 | 10 | For informations on standard SELKS implementation, see https://github.com/StamusNetworks/SELKS#selks 11 | 12 | Minimum Requirements 13 | -------------------- 14 | - 2 cores 15 | - 8 GB of free RAM 16 | - 10 GB of free disk space (actual disk occupation will mainly depend of the number of rules and the amount of traffic on the network). 200GB+ SSD grade is recommended. 17 | - ``git``, ``curl`` 18 | - ``docker`` > 17.06.0 (will be installed during SELKS initial setup) 19 | - ``docker-compose`` > 1.27.0 (will be installed during SELKS initial setup) 20 | 21 | Install process 22 | --------------- 23 | ### Basic installation 24 | 25 | ```bash 26 | git clone https://github.com/StamusNetworks/SELKS.git 27 | cd SELKS/docker/ 28 | ./easy-setup.sh 29 | docker-compose up -d 30 | ``` 31 | 32 | Once the containers are up and running, you should just point your browser to `https://your.selks.IP.here/` 33 | If you chose to install Portainer during the installation, you must visit `https://your.selks.IP.here:9443` to set portainer's admin password 34 | 35 | If the setup script fails and you think it's a bug, please [Report an issue](#report-an-issue). You can also take a look at the [manual setup process](https://github.com/StamusNetworks/SELKS/wiki/Manual-Docker-install) 36 | 37 | ### Credentials and log in 38 | 39 | In order to access scirius, you will need following credentials: 40 | 41 | - user: `selks-user` 42 | - password: `selks-user` 43 | 44 | ### Wiki 45 | 46 | More info and details can be found on our [wiki](https://github.com/StamusNetworks/SELKS/wiki/Docker) 47 | 48 | 49 | ### Advanced installation 50 | 51 | For detailed instructions, please visit the advanced installation guide - [wiki](https://github.com/StamusNetworks/SELKS/wiki/Docker#understanding-the-setup-script) 52 | 53 | Getting help 54 | ------------ 55 | 56 | There are many ways to get help incvluding in our live chat - [Getting Help](https://github.com/StamusNetworks/SELKS/wiki/Getting-Help) 57 | 58 | Report an issue 59 | --------------- 60 | 61 | If you've encoutered an issue please let us know: [Report Issue](https://github.com/StamusNetworks/SELKS/issues/new?labels[]=Docker&title=Docker:%20Issue%20summary&body=%3C%21--%0AUse%20the%20commands%20below%20to%20provide%20key%20information%20from%20your%20environment%3A%0AYou%20do%20NOT%20have%20to%20include%20this%20information%20if%20this%20is%20a%20FEATURE%20REQUEST%0A--%3E%0A%0A%2A%2ADescription%2A%2A%0A%0A%0A%2A%2ASteps%20to%20reproduce%20the%20issue%3A%2A%2A%0A1.%0A2.%0A3.%0A%0A%2A%2ADescribe%20the%20results%20you%20received%3A%2A%2A%0A%0A%0A%2A%2ADescribe%20the%20results%20you%20expected%3A%2A%2A%0A%0A%0A%2A%2AAdditional%20information%20you%20deem%20important%20%28e.g.%20issue%20happens%20only%20occasionally%29%3A%2A%2A%0A%0A%2A%2AOutput%20of%20%60docker%20version%60%3A%2A%2A%0A%0A%60%60%60%0A%28paste%20your%20output%20here%29%0A%60%60%60%0A%0A%2A%2AOutput%20of%20%60docker-compose%20version%60%3A%2A%2A%0A%0A%60%60%60%0A%28paste%20your%20output%20here%29%0A%60%60%60%0A%0A%2A%2AOutput%20of%20%60lsb_release%20-a%60%3A%2A%2A%0A%0A%60%60%60%0A%28paste%20your%20output%20here%29%0A%60%60%60%0A%0A%2A%2AAdditional%20environment%20details%3A%2A%2A%0A) 62 | -------------------------------------------------------------------------------- /docker/containers-data/cron-jobs/README.md: -------------------------------------------------------------------------------- 1 | 2 | Cron jobs are run in an alpine container. It uses the busybox "crond". 3 | Scripts to be run have to be placed into the appropriate folder. 4 | 5 | 6 | This is the crontab root file inside the container : 7 | ```bash 8 | # min hour day month weekday command 9 | */15 * * * * run-parts /etc/periodic/15min 10 | 0 * * * * run-parts /etc/periodic/hourly 11 | 0 2 * * * run-parts /etc/periodic/daily 12 | 0 3 * * 6 run-parts /etc/periodic/weekly 13 | 0 5 1 * * run-parts /etc/periodic/monthly 14 | ``` 15 | where `/etc/periodic/` is mapped on host filesystem at `SELKS/docker/containers-data/cron-jobs/` 16 | -------------------------------------------------------------------------------- /docker/containers-data/cron-jobs/daily/scirius-update-suri-rules.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | echo "Updating Suricata rules from Scirius" 4 | docker exec scirius python /opt/scirius/manage.py updatesuricata && echo "done." || echo "ERROR" 5 | -------------------------------------------------------------------------------- /docker/containers-data/cron-jobs/daily/suricata-logrotate.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # 3 | # Example of rotating the logs within the Suricata container. 4 | # 5 | # Add -v for verbose output. 6 | # Add -f to force rotation. 7 | 8 | echo "Rotating Suricata logs" 9 | docker exec suricata logrotate -v /etc/logrotate.d/suricata $@ && echo "done." || echo "ERROR" 10 | -------------------------------------------------------------------------------- /docker/containers-data/logstash/conf.d/logstash.conf: -------------------------------------------------------------------------------- 1 | input { 2 | file { 3 | path => ["/var/log/suricata/*.json"] 4 | #sincedb_path => ["/var/lib/logstash/"] 5 | sincedb_path => ["/usr/share/logstash/since.db"] 6 | codec => json 7 | type => "SELKS" 8 | } 9 | 10 | } 11 | 12 | filter { 13 | if [type] == "SELKS" { 14 | 15 | date { 16 | match => [ "timestamp", "ISO8601" ] 17 | } 18 | 19 | ruby { 20 | code => " 21 | if event.get('[event_type]') == 'fileinfo' 22 | event.set('[fileinfo][type]', event.get('[fileinfo][magic]').to_s.split(',')[0]) 23 | end 24 | " 25 | } 26 | ruby { 27 | code => " 28 | if event.get('[event_type]') == 'alert' 29 | sp = event.get('[alert][signature]').to_s.split(' group ') 30 | if (sp.length == 2) and /\A\d+\z/.match(sp[1]) 31 | event.set('[alert][signature]', sp[0]) 32 | end 33 | end 34 | " 35 | } 36 | 37 | metrics { 38 | meter => [ "eve_insert" ] 39 | add_tag => "metric" 40 | flush_interval => 30 41 | } 42 | } 43 | 44 | if [http] { 45 | useragent { 46 | source => "[http][http_user_agent]" 47 | target => "[http][user_agent]" 48 | } 49 | } 50 | if [src_ip] { 51 | geoip { 52 | source => "src_ip" 53 | target => "geoip" 54 | #database => "/opt/logstash/vendor/geoip/GeoLiteCity.dat" 55 | #add_field => [ "[geoip][coordinates]", "%{[geoip][longitude]}" ] 56 | #add_field => [ "[geoip][coordinates]", "%{[geoip][latitude]}" ] 57 | } 58 | } 59 | if [dest_ip] { 60 | geoip { 61 | source => "dest_ip" 62 | target => "geoip" 63 | #database => "/opt/logstash/vendor/geoip/GeoLiteCity.dat" 64 | #add_field => [ "[geoip][coordinates]", "%{[geoip][longitude]}" ] 65 | #add_field => [ "[geoip][coordinates]", "%{[geoip][latitude]}" ] 66 | } 67 | } 68 | } 69 | 70 | output { 71 | if [event_type] and [event_type] != 'stats' { 72 | elasticsearch { 73 | hosts => "elasticsearch" 74 | index => "logstash-%{event_type}-%{+YYYY.MM.dd}" 75 | template_overwrite => true 76 | template => "/usr/share/logstash/config/elasticsearch7-template.json" 77 | } 78 | } else { 79 | elasticsearch { 80 | hosts => "elasticsearch" 81 | index => "logstash-%{+YYYY.MM.dd}" 82 | template_overwrite => true 83 | template => "/usr/share/logstash/config/elasticsearch7-template.json" 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /docker/containers-data/logstash/templates/elasticsearch7-template.json: -------------------------------------------------------------------------------- 1 | { 2 | "template" : "logstash-*", 3 | "order": 1, 4 | "version" : 70002, 5 | "index_patterns": [ 6 | "logstash-*" 7 | ], 8 | "settings" : { 9 | "index": { 10 | "number_of_replicas": 0, 11 | "refresh_interval" : "5s", 12 | "mapping.total_fields.limit": 10000 13 | }, 14 | "analysis": { 15 | "analyzer": { 16 | "sn_analyzer": { 17 | "type": "custom", 18 | "tokenizer": "whitespace", 19 | "char_filter": [ 20 | "sn_lowercase" 21 | ] 22 | } 23 | }, 24 | "char_filter": { 25 | "sn_lowercase": { 26 | "type": "mapping", 27 | "mappings": [ 28 | "A => a", "B => b", "C => c", "D => d", "E => e", "F => f", "G => g", "H => h", "I => i", "J => j", "K => k", "L => l", "M => m", "N => n", "O => o", "P => p", "Q => q", "R => r", "S => s", "T => t", "U => u", "V => v", "W => w", "X => x", "Y => y", "Z => z" ] 29 | } 30 | } 31 | } 32 | }, 33 | "mappings" : { 34 | "dynamic_templates" : [ { 35 | "message_field" : { 36 | "path_match" : "message", 37 | "match_mapping_type" : "string", 38 | "mapping" : { 39 | "type" : "text", 40 | "norms" : false, 41 | "analyzer": "sn_analyzer", 42 | "search_analyzer":"sn_analyzer", 43 | "search_quote_analyzer":"sn_analyzer" 44 | } 45 | } 46 | }, { 47 | "string_fields" : { 48 | "match" : "*", 49 | "match_mapping_type" : "string", 50 | "mapping" : { 51 | "type" : "text", "norms" : false, 52 | "analyzer": "sn_analyzer", 53 | "search_analyzer":"sn_analyzer", 54 | "search_quote_analyzer":"sn_analyzer", 55 | "fields" : { 56 | "keyword" : { "type": "keyword", "ignore_above": 256 }, 57 | "raw" : { "type": "keyword", "ignore_above": 256 } 58 | } 59 | } 60 | } 61 | }, { 62 | "percentage_fields_long_to_float": { 63 | "path_match": "*.pct", 64 | "match_mapping_type": "long", 65 | "mapping": { 66 | "type": "float" 67 | } 68 | } 69 | } ], 70 | "properties" : { 71 | "@timestamp": { "type": "date" }, 72 | "@version": { "type": "keyword" }, 73 | "geoip" : { 74 | "dynamic": true, 75 | "properties" : { 76 | "ip": { "type": "ip" }, 77 | "location" : { "type" : "geo_point" }, 78 | "latitude" : { "type" : "half_float" }, 79 | "longitude" : { "type" : "half_float" } 80 | } 81 | }, 82 | "discovery" : { 83 | "dynamic": true, 84 | "properties" : { 85 | "asset": { 86 | "type": "ip", 87 | "fields": { 88 | "raw": {"type": "keyword"}, 89 | "keyword": {"type": "keyword"} 90 | } 91 | } 92 | } 93 | }, 94 | "dest_ip": { 95 | "type": "ip", 96 | "fields": { 97 | "raw": {"type": "keyword"}, 98 | "keyword": {"type": "keyword"} 99 | } 100 | }, 101 | "src_ip": { 102 | "type": "ip", 103 | "fields": { 104 | "raw": {"type": "keyword"}, 105 | "keyword": {"type": "keyword"} 106 | } 107 | }, 108 | "cpu": { 109 | "properties": { 110 | "system_p": { 111 | "doc_values": "true", 112 | "type": "float" 113 | }, 114 | "user_p": { 115 | "doc_values": "true", 116 | "type": "float" 117 | } 118 | } 119 | }, 120 | "fs": { 121 | "properties": { 122 | "used_p": { 123 | "doc_values": "true", 124 | "type": "float" 125 | } 126 | } 127 | }, 128 | "load": { 129 | "properties": { 130 | "load1": { 131 | "doc_values": "true", 132 | "type": "float" 133 | }, 134 | "load15": { 135 | "doc_values": "true", 136 | "type": "float" 137 | }, 138 | "load5": { 139 | "doc_values": "true", 140 | "type": "float" 141 | } 142 | } 143 | }, 144 | "mem": { 145 | "properties": { 146 | "actual_used_p": { 147 | "doc_values": "true", 148 | "type": "float" 149 | }, 150 | "used_p": { 151 | "doc_values": "true", 152 | "type": "float" 153 | } 154 | } 155 | }, 156 | "proc": { 157 | "properties": { 158 | "cpu": { 159 | "properties": { 160 | "user_p": { 161 | "doc_values": "true", 162 | "type": "float" 163 | } 164 | } 165 | }, 166 | "mem": { 167 | "properties": { 168 | "rss_p": { 169 | "doc_values": "true", 170 | "type": "float" 171 | } 172 | } 173 | } 174 | } 175 | }, 176 | "swap": { 177 | "properties": { 178 | "used_p": { 179 | "doc_values": "true", 180 | "type": "float" 181 | } 182 | } 183 | }, 184 | "ip": { 185 | "type": "ip" 186 | }, 187 | "alert": { 188 | "properties": { 189 | "source": { 190 | "properties": { 191 | "ip": { 192 | "type": "ip", 193 | "fields": { 194 | "keyword": {"type": "keyword"} 195 | } 196 | } 197 | } 198 | }, 199 | "target": { 200 | "properties": { 201 | "ip": { 202 | "type": "ip", 203 | "fields": { 204 | "keyword": {"type": "keyword"} 205 | } 206 | } 207 | } 208 | } 209 | } 210 | } 211 | } 212 | } 213 | } 214 | -------------------------------------------------------------------------------- /docker/containers-data/nginx/conf.d/selks6.conf: -------------------------------------------------------------------------------- 1 | server { 2 | listen 80 default_server; 3 | listen 443 default_server ssl; 4 | ssl_certificate /etc/nginx/ssl/scirius.crt; 5 | ssl_certificate_key /etc/nginx/ssl/scirius.key; 6 | server_name SELKS; 7 | access_log /var/log/nginx/scirius.access.log; 8 | error_log /var/log/nginx/scirius.error.log; 9 | 10 | # https://docs.djangoproject.com/en/dev/howto/static-files/#serving-static-files-in-production 11 | location /static/ { # STATIC_URL 12 | alias /static/; # STATIC_ROOT 13 | expires 30d; 14 | } 15 | 16 | location /media/ { # MEDIA_URL 17 | alias /static/; # MEDIA_ROOT 18 | expires 30d; 19 | } 20 | 21 | location /plugins/ { 22 | proxy_pass http://kibana:5601/plugins/; 23 | proxy_redirect off; 24 | } 25 | 26 | location /dlls/ { 27 | proxy_pass http://kibana:5601/dlls/; 28 | proxy_redirect off; 29 | } 30 | 31 | location /socket.io/ { 32 | proxy_pass http://kibana:5601/socket.io/; 33 | proxy_redirect off; 34 | } 35 | 36 | location /dataset/ { 37 | proxy_pass http://kibana:5601/dataset/; 38 | proxy_redirect off; 39 | } 40 | 41 | location /translations/ { 42 | proxy_pass http://kibana:5601/translations/; 43 | proxy_redirect off; 44 | } 45 | 46 | location ^~ /built_assets/ { 47 | proxy_pass http://kibana:5601/built_assets/; 48 | proxy_redirect off; 49 | } 50 | 51 | location /ui/ { 52 | proxy_pass http://kibana:5601/ui/; 53 | proxy_redirect off; 54 | } 55 | 56 | location /spaces/ { 57 | proxy_pass http://kibana:5601/spaces/; 58 | proxy_redirect off; 59 | } 60 | 61 | location /node_modules/ { 62 | proxy_pass http://kibana:5601/node_modules/; 63 | proxy_redirect off; 64 | } 65 | 66 | location /bootstrap.js { 67 | proxy_pass http://kibana:5601/bootstrap.js; 68 | proxy_redirect off; 69 | } 70 | 71 | location /internal/ { 72 | proxy_pass http://kibana:5601/internal/; 73 | proxy_redirect off; 74 | } 75 | 76 | location ~ "^/([\d]{5}/.*)" { 77 | proxy_pass http://kibana:5601/$1; 78 | proxy_redirect off; 79 | } 80 | 81 | 82 | location / { 83 | proxy_pass http://scirius:8000; 84 | proxy_read_timeout 600; 85 | proxy_set_header Host $http_host; 86 | proxy_set_header X-Forwarded-Proto https; 87 | proxy_redirect off; 88 | client_max_body_size 100M; 89 | } 90 | 91 | } 92 | 93 | -------------------------------------------------------------------------------- /docker/containers-data/nginx/nginx.conf: -------------------------------------------------------------------------------- 1 | user www-data; 2 | worker_processes auto; 3 | pid /run/nginx.pid; 4 | include /etc/nginx/modules-enabled/*.conf; 5 | 6 | events { 7 | worker_connections 768; 8 | # multi_accept on; 9 | } 10 | 11 | http { 12 | 13 | ## 14 | # Basic Settings 15 | ## 16 | 17 | sendfile on; 18 | tcp_nopush on; 19 | tcp_nodelay on; 20 | keepalive_timeout 65; 21 | types_hash_max_size 2048; 22 | client_max_body_size 20M; 23 | # server_tokens off; 24 | 25 | # server_names_hash_bucket_size 64; 26 | # server_name_in_redirect off; 27 | 28 | include /etc/nginx/mime.types; 29 | default_type application/octet-stream; 30 | 31 | ## 32 | # SSL Settings 33 | ## 34 | 35 | ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE 36 | ssl_prefer_server_ciphers on; 37 | 38 | ## 39 | # Logging Settings 40 | ## 41 | 42 | access_log /var/log/nginx/access.log; 43 | error_log /var/log/nginx/error.log; 44 | 45 | ## 46 | # Gzip Settings 47 | ## 48 | 49 | gzip on; 50 | 51 | # gzip_vary on; 52 | # gzip_proxied any; 53 | # gzip_comp_level 6; 54 | # gzip_buffers 16 8k; 55 | # gzip_http_version 1.1; 56 | # gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript; 57 | 58 | ## 59 | # Virtual Host Configs 60 | ## 61 | 62 | include /etc/nginx/conf.d/*.conf; 63 | #include /etc/nginx/sites-enabled/*; 64 | } 65 | 66 | 67 | #mail { 68 | # # See sample authentication script at: 69 | # # http://wiki.nginx.org/ImapAuthenticateWithApachePhpScript 70 | # 71 | # # auth_http localhost/auth.php; 72 | # # pop3_capabilities "TOP" "USER"; 73 | # # imap_capabilities "IMAP4rev1" "UIDPLUS"; 74 | # 75 | # server { 76 | # listen localhost:110; 77 | # protocol pop3; 78 | # proxy on; 79 | # } 80 | # 81 | # server { 82 | # listen localhost:143; 83 | # protocol imap; 84 | # proxy on; 85 | # } 86 | #} 87 | -------------------------------------------------------------------------------- /docker/containers-data/suricata/etc/new_entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | fix_perms() { 5 | if [[ "${PGID}" ]]; then 6 | groupmod -o -g "${PGID}" suricata 7 | fi 8 | 9 | if [[ "${PUID}" ]]; then 10 | usermod -o -u "${PUID}" suricata 11 | fi 12 | 13 | chown -R suricata:suricata /etc/suricata 14 | chown -R suricata:suricata /var/lib/suricata 15 | chown -R suricata:suricata /var/log/suricata 16 | chown -R suricata:suricata /var/run/suricata 17 | } 18 | 19 | for src in /etc/suricata.dist/*; do 20 | filename=$(basename ${src}) 21 | dst="/etc/suricata/${filename}" 22 | if ! test -e "${dst}"; then 23 | echo "Creating ${dst}." 24 | cp -a "${src}" "${dst}" 25 | fi 26 | done 27 | 28 | mkdir -p /var/log/suricata/fpc/ 29 | cat /etc/suricata/suricata.yaml | grep "include: selks6-addin.yaml" || echo "include: selks6-addin.yaml" >> /etc/suricata/suricata.yaml && echo 'suricata.yaml edited' 30 | 31 | exec /docker-entrypoint.sh $@ -------------------------------------------------------------------------------- /docker/scripts/cleanup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Copyright(C) 2021, Stamus Networks 4 | # Written by Raphaël Brogat <rbrogat@stamus-networks.com> 5 | # 6 | # This script comes with ABSOLUTELY NO WARRANTY! 7 | # 8 | # GPLv3 <http://www.gnu.org/licenses/>. 9 | 10 | BASEDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )/.." &> /dev/null && pwd )" 11 | 12 | function Help(){ 13 | # Display Help 14 | { echo "*** cleanup.sh help ***" 15 | echo 16 | echo "Use this script to remove all data from elasticsearch and suricata" 17 | echo "Containers must be running for the data to be removed" 18 | echo 19 | echo -e " Syntax: cleanup.sh" 20 | echo 21 | echo 22 | 23 | } | fmt 24 | } 25 | 26 | if [ $# -gt 0 ]; then 27 | Help 28 | exit -1 29 | fi 30 | 31 | 32 | ## TEMPORARY FIX WHILE PERMISSION ISSUE 33 | if (( $EUID != 0 )); then 34 | echo -e "Please run this script as root or with \"sudo\".\n" 35 | exit 1 36 | fi 37 | 38 | # TEST IF DOCKER IS ACCESSIBLE TO THIS USER ## 39 | dockerV=$(docker version --format '{{.Server.Version}}' 2>/dev/null) 40 | if [[ -z "$dockerV" ]]; then 41 | echo "Please run this script as root or with sudo" 42 | exit 1 43 | fi 44 | 45 | echo "Delete suricata logs:" 46 | rm -rf ${BASEDIR}/containers-data/suricata/logs/* && echo -e "OK\n" || { echo -e "ERROR\n" && exit 1; } 47 | 48 | echo "Deleting data from arkime" 49 | docker exec arkime bash -c "printf 'WIPE\n' | /opt/arkime/db/db.pl http://elasticsearch:9200 wipe" | grep -q "Finished" && echo -e "OK\n" || echo -e "ERROR\n" 50 | 51 | echo "send SIGHUP to suricata:" 52 | docker kill --signal=HUP suricata | grep -q "suricata" && echo -e "OK\n" || echo -e "ERROR\n" 53 | 54 | echo "Delete elasticsearch indexes:" 55 | OUT=$( docker exec scirius curl -s -X DELETE -i 'http://elasticsearch:9200/logstash-*' ) 56 | echo "${OUT}" | grep -q "200 OK" && echo -e "OK\n" || { echo -e "ERROR\n ${OUT}\n" && exit 1; } 57 | -------------------------------------------------------------------------------- /install-deps.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright Stamus Networks 4 | # All rights reserved 5 | # Debian Live ISO script - oss@stamus-networks.com 6 | # 7 | 8 | set -e 9 | 10 | # Install needed packages for default build 11 | apt-get -y install xorriso live-build syslinux squashfs-tools python-docutils 12 | 13 | # Install needed packages for the choose your own kernel option 14 | apt-get -y install wget fakeroot gcc libncurses5-dev bc \ 15 | ca-certificates pkg-config make flex bison build-essential autoconf \ 16 | automake aptitude 17 | -------------------------------------------------------------------------------- /kubernetes/README.md: -------------------------------------------------------------------------------- 1 | SELKS on Kubernetes 2 | =============== 3 | 4 | Intro 5 | ----- 6 | 7 | This version of SELKS is based on docker and intended to provide easier deployment and management on Kubernetes 8 | 9 | For informations on standard SELKS implementation, see https://github.com/StamusNetworks/SELKS#selks 10 | 11 | Minimum Requirements 12 | -------------------- 13 | - 2 cores 14 | - 8 GB of free RAM 15 | - 10 GB of free disk space (actual disk occupation will mainly depend of the number of rules and the amount of traffic on the network). 200GB+ SSD grade is recommended. 16 | - ``git``, ``curl`` 17 | - ``Kubernetes`` >= 1.21 (tested on k3s 1.22 to 1.25) 18 | - ``containerd`` (Docker not supported from Kubernetes 1.24) 19 | 20 | Install process 21 | --------------- 22 | ### Basic installation 23 | Clone the Git repository from SELKS: 24 | 25 | ```bash 26 | git clone https://github.com/StamusNetworks/SELKS.git 27 | cd SELKS/kubernetes/ 28 | ``` 29 | 30 | The default installation comes with Filebeat and Logstash, however there is the option of switching to Fluent-bit and Fluentd. The biggest advantage is in terms of memory usage, the Fluent stack uses rather significantly less memory (Logstash uses 1G to 1,5G by default, Fluentd uses about 100M. Filebeat uses 100M, Fluent-bit uses 10). The disadvantage is that in order to be able to use the full functionality that the default Elastic stack provides you are required to build and use your own container image with certain plugins. An example Docker file is provided for ease of use, however this doesn't include the GeoIP database and plugin. If you want to switch to the Fluent stack, edit the `install.sh` file to your needs. Please note the use of the Fluent stack is not officially supported by us! 31 | 32 | 33 | First create the directories to be used by SELKS. You can of course deviate from the provided example of `/data`, but be sure to update the PV's for all components. 34 | 35 | ```bash 36 | mkdir -p /data/arkime/{pcap,logs} /data/suricata/{logrotate,rules,run,logs/fpc} /data/scirius/{data,logs,static} /data/elasticsearch 37 | chown -R 997:995 /data/suricata 38 | chown -R 1000:995 /data/scirius 39 | chown -R 1000:1000 /data/elasticsearch 40 | chown -R 1000:1000 /data/arkime 41 | ``` 42 | 43 | Next, you have to update the PV's according to your own needs. The default PV's provided in this repository have been tested against k3s, which uses nodeAffinity with hostnames to bind the PV to the host. At minimum, you'll need to update the hostnames. The command below replaces the hostname in all of the PV's, and also the ingress and Arkime ConfigMap. 44 | ```bash 45 | find . -type f -name "*.yaml" -exec sed -i 's/HOSTNAME/yourHostname/g' '{}' \; 46 | ``` 47 | 48 | To change the default username and password used by Scirius, navigate to scirius/scirius-secret.yaml and update the values. You can generate new values with the following command: 49 | ```bash 50 | echo -n "yourBeautifulPassword" | base64 51 | ``` 52 | 53 | Navigate to `suricata/suricata-daemonset.yaml` and ajust the interface name to your needs. Currently only one interface name is supported, so make sure when using multiple nodes that all interface names are the same. 54 | ```yaml 55 | - name: SURICATA_OPTIONS 56 | value: "-i eth0 -vvv --set sensor-name=suricata [...] 57 | ^^^^ 58 | ``` 59 | 60 | When using TLS, you'll need to either generate a certificate for the ingress of use a tool like cert-manager to generate one for you 61 | ```bash 62 | openssl req -new -nodes -x509 -subj "/C=FR/ST=IDF/L=Paris/O=Stamus/CN=SELKS" -days 3650 -keyout ./tls.key -out tls.crt -extensions v3_ca 63 | kubectl create secret tls nginx-tls --cert=tls.crt --key=tls.key --dry-run=client -o yaml > nginx/nginx-secret.yaml 64 | ``` 65 | 66 | Now you're ready for installation; set execute permission on the installation script and run it. 67 | ```bash 68 | chmod +x install.sh 69 | ./install.sh 70 | ``` 71 | 72 | Once Kibana is up and running, you can use the provided Job to load the default SELKS dashboards. 73 | 74 | ```bash 75 | kubectl create --save-config -f kibana/kibana-dashboards-job.yaml 76 | ``` 77 | 78 | Once the services have been applied, you can get the NodePort using the following command: 79 | ```bash 80 | kubectl get svc -n suricata nginx 81 | ``` 82 | 83 | In the example below, 31584 is the NodePort to connect to. 84 | ```bash 85 | NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE 86 | nginx NodePort 10.43.233.61 <none> 443:31584/TCP,80:30831/TCP 27h 87 | ``` 88 | 89 | Once the deployments are up and running, you should just point your browser to `https://your.selks.IP.here:31584/` 90 | 91 | Alternatively, you can alter and apply the nginx-ingress YAML definition and access the cluster via FQDN. 92 | 93 | ### Credentials and log in 94 | 95 | In order to access scirius, you will need following credentials (unless you changed them): 96 | 97 | - user: `selks-user` 98 | - password: `selks-user` 99 | 100 | ### Wiki 101 | 102 | More info and details can be found on our [wiki](https://github.com/StamusNetworks/SELKS/wiki/Docker) 103 | 104 | 105 | Getting help 106 | ------------ 107 | 108 | There are many ways to get help including in our live chat - [Getting Help](https://github.com/StamusNetworks/SELKS/wiki/Getting-Help) 109 | 110 | Report an issue 111 | --------------- 112 | 113 | If you've encoutered an issue please let us know: [Report Issue](https://github.com/StamusNetworks/SELKS/issues/new?labels[]=Docker&title=Docker:%20Issue%20summary&body=%3C%21--%0AUse%20the%20commands%20below%20to%20provide%20key%20information%20from%20your%20environment%3A%0AYou%20do%20NOT%20have%20to%20include%20this%20information%20if%20this%20is%20a%20FEATURE%20REQUEST%0A--%3E%0A%0A%2A%2ADescription%2A%2A%0A%0A%0A%2A%2ASteps%20to%20reproduce%20the%20issue%3A%2A%2A%0A1.%0A2.%0A3.%0A%0A%2A%2ADescribe%20the%20results%20you%20received%3A%2A%2A%0A%0A%0A%2A%2ADescribe%20the%20results%20you%20expected%3A%2A%2A%0A%0A%0A%2A%2AAdditional%20information%20you%20deem%20important%20%28e.g.%20issue%20happens%20only%20occasionally%29%3A%2A%2A%0A%0A%2A%2AOutput%20of%20%60docker%20version%60%3A%2A%2A%0A%0A%60%60%60%0A%28paste%20your%20output%20here%29%0A%60%60%60%0A%0A%2A%2AOutput%20of%20%60docker-compose%20version%60%3A%2A%2A%0A%0A%60%60%60%0A%28paste%20your%20output%20here%29%0A%60%60%60%0A%0A%2A%2AOutput%20of%20%60lsb_release%20-a%60%3A%2A%2A%0A%0A%60%60%60%0A%28paste%20your%20output%20here%29%0A%60%60%60%0A%0A%2A%2AAdditional%20environment%20details%3A%2A%2A%0A) 114 | -------------------------------------------------------------------------------- /kubernetes/arkime/arkime-deployment.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | apiVersion: apps/v1 4 | kind: Deployment 5 | metadata: 6 | annotations: 7 | labels: 8 | app: arkime 9 | name: arkime 10 | namespace: suricata 11 | spec: 12 | replicas: 1 13 | selector: 14 | matchLabels: 15 | app: arkime 16 | template: 17 | metadata: 18 | annotations: 19 | labels: 20 | app: arkime 21 | spec: 22 | containers: 23 | - name: arkime 24 | image: ghcr.io/stamusnetworks/arkimeviewer:master 25 | env: 26 | - name: ES_HOST 27 | value: elasticsearch.logging 28 | - name: ES_PORT 29 | value: "9200" 30 | - name: ARKIME_ADMIN_USERNAME 31 | valueFrom: 32 | secretKeyRef: 33 | name: arkime-secret 34 | key: username 35 | - name: ARKIME_ADMIN_PASSWORD 36 | valueFrom: 37 | secretKeyRef: 38 | name: arkime-secret 39 | key: password 40 | 41 | ports: 42 | - containerPort: 8005 43 | 44 | resources: 45 | requests: 46 | memory: 250Mi 47 | cpu: 100m 48 | limits: 49 | cpu: 1 50 | memory: 1Gi 51 | 52 | # securityContext: 53 | # capabilities: 54 | # drop: 55 | # - ALL 56 | # runAsNonRoot: true 57 | 58 | volumeMounts: 59 | - mountPath: /data/config/config.ini 60 | name: arkime-config 61 | subPath: config.ini 62 | - mountPath: /opt/arkime/logs 63 | name: arkime-log 64 | - mountPath: /suricata-logs 65 | name: suricata-log 66 | readOnly: True 67 | 68 | restartPolicy: Always 69 | volumes: 70 | - name: arkime-config 71 | configMap: 72 | name: arkime-config 73 | items: 74 | - key: arkimepcapread-selks-config.ini 75 | path: config.ini 76 | - name: arkime-log 77 | persistentVolumeClaim: 78 | claimName: arkime-log 79 | - name: suricata-log 80 | persistentVolumeClaim: 81 | claimName: suricata-log 82 | -------------------------------------------------------------------------------- /kubernetes/arkime/arkime-pv.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | apiVersion: v1 4 | kind: PersistentVolume 5 | metadata: 6 | name: arkime-log 7 | spec: 8 | capacity: 9 | storage: 1Gi 10 | volumeMode: Filesystem 11 | accessModes: 12 | - ReadWriteOnce 13 | persistentVolumeReclaimPolicy: Retain 14 | claimRef: 15 | name: arkime-log 16 | namespace: suricata 17 | local: 18 | path: /data/arkime/logs/ 19 | nodeAffinity: 20 | required: 21 | nodeSelectorTerms: 22 | - matchExpressions: 23 | - key: kubernetes.io/hostname 24 | operator: In 25 | values: 26 | - HOSTNAME 27 | -------------------------------------------------------------------------------- /kubernetes/arkime/arkime-pvc.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | apiVersion: v1 4 | kind: PersistentVolumeClaim 5 | metadata: 6 | labels: 7 | app: arkime-log 8 | name: arkime-log 9 | namespace: suricata 10 | spec: 11 | storageClassName: "local-storage" 12 | volumeName: arkime-log 13 | accessModes: 14 | - ReadWriteOnce 15 | resources: 16 | requests: 17 | storage: 1Gi 18 | -------------------------------------------------------------------------------- /kubernetes/arkime/arkime-secret.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Secret 3 | metadata: 4 | name: arkime-secret 5 | type: kubernetes.io/basic-auth 6 | stringData: 7 | username: YWRtaW4= 8 | password: YWRtaW4= 9 | -------------------------------------------------------------------------------- /kubernetes/arkime/arkime-service.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | apiVersion: v1 4 | kind: Service 5 | metadata: 6 | name: arkime 7 | namespace: suricata 8 | labels: 9 | app: arkime 10 | spec: 11 | type: ClusterIP 12 | ports: 13 | - port: 8005 14 | protocol: TCP 15 | name: http 16 | targetPort: 8005 17 | selector: 18 | app: arkime 19 | -------------------------------------------------------------------------------- /kubernetes/common/logging-ns.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | apiVersion: v1 4 | kind: Namespace 5 | metadata: 6 | name: logging 7 | labels: 8 | kubernetes.io/metadata.name: logging 9 | -------------------------------------------------------------------------------- /kubernetes/common/storageclass.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | apiVersion: storage.k8s.io/v1 4 | kind: StorageClass 5 | metadata: 6 | name: local-storage 7 | provisioner: kubernetes.io/no-provisioner 8 | volumeBindingMode: WaitForFirstConsumer 9 | -------------------------------------------------------------------------------- /kubernetes/common/suricata-ns.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | apiVersion: v1 4 | kind: Namespace 5 | metadata: 6 | name: suricata 7 | labels: 8 | kubernetes.io/metadata.name: suricata 9 | -------------------------------------------------------------------------------- /kubernetes/elasticsearch/elasticsearch-pv.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | apiVersion: v1 4 | kind: PersistentVolume 5 | metadata: 6 | name: elasticsearch-data 7 | spec: 8 | capacity: 9 | storage: 50Gi 10 | volumeMode: Filesystem 11 | accessModes: 12 | - ReadWriteOnce 13 | persistentVolumeReclaimPolicy: Retain 14 | claimRef: 15 | name: elasticsearch-data 16 | namespace: logging 17 | local: 18 | path: /data/elasticsearch/ 19 | nodeAffinity: 20 | required: 21 | nodeSelectorTerms: 22 | - matchExpressions: 23 | - key: kubernetes.io/hostname 24 | operator: In 25 | values: 26 | - HOSTNAME 27 | -------------------------------------------------------------------------------- /kubernetes/elasticsearch/elasticsearch-pvc.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | apiVersion: v1 4 | kind: PersistentVolumeClaim 5 | metadata: 6 | labels: 7 | app: elasticsearch-data 8 | name: elasticsearch-data 9 | namespace: logging 10 | spec: 11 | storageClassName: "local-storage" 12 | volumeName: elasticsearch-data 13 | accessModes: 14 | - ReadWriteOnce 15 | resources: 16 | requests: 17 | storage: 50Gi 18 | -------------------------------------------------------------------------------- /kubernetes/elasticsearch/elasticsearch-service.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: Service 4 | metadata: 5 | name: es 6 | labels: 7 | service: elasticsearch 8 | namespace: logging 9 | spec: 10 | # Setting clusterIP to none makes sure communication is directly between pods 11 | clusterIP: None 12 | ports: 13 | - port: 9300 14 | name: transport 15 | selector: 16 | service: elasticsearch 17 | 18 | --- 19 | apiVersion: v1 20 | kind: Service 21 | metadata: 22 | labels: 23 | service: elasticsearch 24 | name: elasticsearch 25 | namespace: logging 26 | spec: 27 | ports: 28 | - port: 9200 29 | protocol: TCP 30 | targetPort: 9200 31 | name: http 32 | selector: 33 | service: elasticsearch 34 | -------------------------------------------------------------------------------- /kubernetes/elasticsearch/elasticsearch-statefulset.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | # Source: elasticsearch/templates/configmap-initcontainer.yaml 3 | apiVersion: v1 4 | kind: ConfigMap 5 | metadata: 6 | name: elasticsearch-initcontainer 7 | labels: 8 | app.kubernetes.io/name: elasticsearch 9 | namespace: logging 10 | data: 11 | folder-setup.sh: |- 12 | #!/bin/bash 13 | 14 | set -o errexit 15 | set -o pipefail 16 | set -o nounset 17 | 18 | mkdir -p /data/$NODE_NAME/logs/ 19 | 20 | --- 21 | 22 | apiVersion: apps/v1 23 | kind: StatefulSet 24 | metadata: 25 | name: elasticsearch 26 | labels: 27 | service: elasticsearch 28 | namespace: logging 29 | spec: 30 | updateStrategy: 31 | type: RollingUpdate 32 | selector: 33 | matchLabels: 34 | service: elasticsearch 35 | replicas: 1 36 | serviceName: es 37 | template: 38 | metadata: 39 | labels: 40 | service: elasticsearch 41 | serviceName: es 42 | spec: 43 | automountServiceAccountToken: false 44 | terminationGracePeriodSeconds: 120 45 | 46 | initContainers: 47 | - name: configure-sysctl 48 | securityContext: 49 | runAsUser: 0 50 | privileged: true 51 | image: "docker.elastic.co/elasticsearch/elasticsearch:7.17.9" 52 | imagePullPolicy: "IfNotPresent" 53 | command: ["bash","-c"] 54 | args: 55 | - | 56 | sysctl -w vm.max_map_count=262144 57 | sysctl -w fs.file-max=65536 58 | 59 | - name: es-folder-prepare 60 | image: bitnami/minideb:buster 61 | env: 62 | - name: NODE_NAME 63 | valueFrom: 64 | fieldRef: 65 | fieldPath: metadata.name 66 | imagePullPolicy: "IfNotPresent" 67 | command: 68 | - /scripts/folder-setup.sh 69 | 70 | securityContext: 71 | allowPrivilegeEscalation: false 72 | capabilities: 73 | drop: 74 | - ALL 75 | privileged: false 76 | runAsGroup: 1000 77 | runAsNonRoot: true 78 | runAsUser: 1000 79 | seccompProfile: 80 | type: RuntimeDefault 81 | 82 | volumeMounts: 83 | - name: initcontainer-script 84 | mountPath: /scripts/folder-setup.sh 85 | subPath: folder-setup.sh 86 | - name: elasticsearch-data 87 | mountPath: /data 88 | 89 | containers: 90 | - name: elasticsearch 91 | image: "docker.elastic.co/elasticsearch/elasticsearch:7.17.9" 92 | env: 93 | - name: cluster.name 94 | value: elasticsearch.cluster.local 95 | - name: node.name 96 | valueFrom: 97 | fieldRef: 98 | fieldPath: metadata.name 99 | 100 | - name: network.host 101 | value: "0.0.0.0" 102 | - name: cluster.deprecation_indexing.enabled 103 | value: "false" 104 | - name: node.roles 105 | value: "transform, data_frozen, master, remote_cluster_client, data, ml, data_content, data_hot, data_warm, data_cold, ingest" 106 | - name: discovery.type 107 | value: single-node 108 | - name: ingest.geoip.downloader.enabled 109 | value: "false" 110 | - name: xpack.security.enabled 111 | value: "false" 112 | # ES 7 with Java 9 113 | - name: ES_JAVA_OPTS 114 | value: "-Xms512m -Xmx512m -XX:HeapDumpPath=/data/$(node.name)/data -XX:ErrorFile=/data/$(node.name)/logs/hs_err_pid%p.log -Xlog:gc*,gc+age=trace,safepoint:file=/data/$(node.name)/logs/@loggc@:utctime,pid,tags:filecount=32,filesize=64m" 115 | 116 | - name: action.auto_create_index 117 | value: ".watches,.triggered_watches,.watcher-history-*,logstash-*,logstash-kube-*,logstash-systemd-*" 118 | 119 | - name: path.data 120 | value: "/data/$(node.name)/data" 121 | - name: path.logs 122 | value: "/data/$(node.name)/logs" 123 | 124 | ports: 125 | - containerPort: 9200 126 | name: http 127 | - containerPort: 9300 128 | name: transport 129 | 130 | securityContext: 131 | allowPrivilegeEscalation: false 132 | capabilities: 133 | drop: 134 | - ALL 135 | privileged: false 136 | runAsGroup: 1000 137 | runAsNonRoot: true 138 | runAsUser: 1000 139 | seccompProfile: 140 | type: RuntimeDefault 141 | 142 | readinessProbe: 143 | exec: 144 | command: 145 | - bash 146 | - -c 147 | - | 148 | set -e 149 | # If the node is starting up wait for the cluster to be ready (request params: "wait_for_status=green&timeout=1s" ) 150 | # Once it has started only check that the node itself is responding 151 | START_FILE=/tmp/.es_start_file 152 | 153 | # Disable nss cache to avoid filling dentry cache when calling curl 154 | # This is required with Elasticsearch Docker using nss < 3.52 155 | export NSS_SDB_USE_CACHE=no 156 | 157 | http () { 158 | local path="${1}" 159 | local args="${2}" 160 | set -- -XGET -s 161 | 162 | if [ "$args" != "" ]; then 163 | set -- "$@" $args 164 | fi 165 | 166 | if [ -n "${ELASTIC_PASSWORD}" ]; then 167 | set -- "$@" -u "elastic:${ELASTIC_PASSWORD}" 168 | fi 169 | 170 | curl --output /dev/null -k "$@" "http://127.0.0.1:9200${path}" 171 | } 172 | 173 | if [ -f "${START_FILE}" ]; then 174 | echo 'Elasticsearch is already running, lets check the node is healthy' 175 | HTTP_CODE=$(http "/" "-w %{http_code}") 176 | RC=$? 177 | if [[ ${RC} -ne 0 ]]; then 178 | echo "curl --output /dev/null -k -XGET -s -w '%{http_code}' \${BASIC_AUTH} http://127.0.0.1:9200/ failed with RC ${RC}" 179 | exit ${RC} 180 | fi 181 | # ready if HTTP code 200, 503 is tolerable if ES version is 6.x 182 | if [[ ${HTTP_CODE} == "200" ]]; then 183 | exit 0 184 | elif [[ ${HTTP_CODE} == "503" && "7" == "6" ]]; then 185 | exit 0 186 | else 187 | echo "curl --output /dev/null -k -XGET -s -w '%{http_code}' \${BASIC_AUTH} http://127.0.0.1:9200/ failed with HTTP code ${HTTP_CODE}" 188 | exit 1 189 | fi 190 | 191 | else 192 | echo 'Waiting for elasticsearch cluster to become ready (request params: "wait_for_status=green&timeout=1s" )' 193 | if http "/_cluster/health?wait_for_status=green&timeout=1s" "--fail" ; then 194 | touch ${START_FILE} 195 | exit 0 196 | else 197 | echo 'Cluster is not yet ready (request params: "wait_for_status=green&timeout=1s" )' 198 | exit 1 199 | fi 200 | fi 201 | failureThreshold: 3 202 | initialDelaySeconds: 10 203 | periodSeconds: 10 204 | successThreshold: 3 205 | timeoutSeconds: 5 206 | 207 | resources: 208 | limits: 209 | cpu: 1000m 210 | memory: 1500Mi 211 | requests: 212 | cpu: 500m 213 | memory: 1500Mi 214 | 215 | volumeMounts: 216 | - mountPath: /data 217 | name: elasticsearch-data 218 | 219 | securityContext: 220 | fsGroup: 1000 221 | seccompProfile: 222 | type: RuntimeDefault 223 | 224 | nodeSelector: 225 | kubernetes.io/os: linux 226 | affinity: 227 | podAntiAffinity: 228 | requiredDuringSchedulingIgnoredDuringExecution: 229 | - topologyKey: kubernetes.io/hostname 230 | labelSelector: 231 | matchLabels: 232 | service: elasticsearch 233 | 234 | volumes: 235 | - name: initcontainer-script 236 | configMap: 237 | name: elasticsearch-initcontainer 238 | defaultMode: 0755 239 | - name: elasticsearch-data 240 | persistentVolumeClaim: 241 | claimName: elasticsearch-data 242 | 243 | restartPolicy: Always 244 | -------------------------------------------------------------------------------- /kubernetes/evebox/evebox-deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | annotations: 5 | labels: 6 | app: evebox 7 | name: evebox 8 | namespace: logging 9 | spec: 10 | replicas: 1 11 | selector: 12 | matchLabels: 13 | app: evebox 14 | template: 15 | metadata: 16 | annotations: 17 | labels: 18 | app: evebox 19 | spec: 20 | automountServiceAccountToken: false 21 | 22 | containers: 23 | - args: 24 | - -e 25 | - http://elasticsearch.logging:9200 26 | image: jasonish/evebox:main 27 | name: evebox 28 | 29 | ports: 30 | - name: web 31 | containerPort: 5636 32 | 33 | resources: 34 | requests: 35 | memory: 50Mi 36 | cpu: 50m 37 | limits: 38 | cpu: 100m 39 | memory: 100Mi 40 | 41 | livenessProbe: 42 | httpGet: 43 | path: / 44 | port: web 45 | readinessProbe: 46 | httpGet: 47 | path: / 48 | port: web 49 | # Need to wait for Elasticsearch 50 | startupProbe: 51 | failureThreshold: 6 52 | initialDelaySeconds: 10 53 | periodSeconds: 10 54 | successThreshold: 1 55 | timeoutSeconds: 5 56 | httpGet: 57 | path: / 58 | port: web 59 | 60 | securityContext: 61 | allowPrivilegeEscalation: false 62 | capabilities: 63 | drop: 64 | - ALL 65 | readOnlyRootFilesystem: true 66 | runAsGroup: 10000 67 | runAsNonRoot: true 68 | runAsUser: 10000 69 | seccompProfile: 70 | type: RuntimeDefault 71 | 72 | restartPolicy: Always 73 | -------------------------------------------------------------------------------- /kubernetes/evebox/evebox-service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | annotations: 5 | labels: 6 | app: evebox 7 | name: evebox 8 | namespace: logging 9 | spec: 10 | ports: 11 | - name: "web" 12 | port: 5636 13 | targetPort: 5636 14 | selector: 15 | app: evebox 16 | sessionAffinity: None 17 | type: ClusterIP 18 | -------------------------------------------------------------------------------- /kubernetes/fluentd_fluent-bit/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM fluent/fluentd-kubernetes-daemonset:v1.14.5-debian-elasticsearch7-amd64-1.1 2 | USER root 3 | RUN ["gem", "install", "fluent-plugin-record-modifier", "--no-document"] 4 | RUN ["gem", "install", "fluent-plugin-ua-parser", "--no-document"] 5 | 6 | # GeoIP requires some more build options, rather than just a simple plugin. 7 | # RUN ["gem", "install", "fluent-plugin-geoip", "--no-document"] 8 | USER fluent 9 | -------------------------------------------------------------------------------- /kubernetes/fluentd_fluent-bit/fluentbit-configmap.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: ConfigMap 4 | metadata: 5 | name: fluent-bit-config 6 | namespace: suricata 7 | data: 8 | fluent-bit.conf: | 9 | [SERVICE] 10 | Daemon Off 11 | Flush 1 12 | Log_Level info 13 | Parsers_File parsers.conf 14 | HTTP_Server On 15 | HTTP_Listen 0.0.0.0 16 | HTTP_Port 2020 17 | Health_Check On 18 | 19 | @INCLUDE input.conf 20 | @INCLUDE filter-kubernetes.conf 21 | @INCLUDE filter-suricata.conf 22 | @INCLUDE output.conf 23 | 24 | input.conf: | 25 | [INPUT] 26 | Name systemd 27 | Tag systemd.* 28 | Systemd_Filter _SYSTEMD_UNIT=kubelet.service 29 | Systemd_Filter _SYSTEMD_UNIT=k3s.service 30 | Systemd_Filter _SYSTEMD_UNIT=sshd.service 31 | Systemd_Filter _SYSTEMD_UNIT=containerd.service 32 | Systemd_Filter _SYSTEMD_UNIT=docker.service 33 | Read_From_Tail On 34 | Strip_Underscores On 35 | Lowercase On 36 | 37 | [INPUT] 38 | Name tail 39 | Tag kube.* 40 | Path /var/log/containers/*.log 41 | multiline.parser docker, cri 42 | DB /var/log/flb_kube.db 43 | Mem_Buf_Limit 5MB 44 | Skip_Long_Lines On 45 | Refresh_Interval 10 46 | 47 | [INPUT] 48 | Name tail 49 | Tag eve_json 50 | Path /var/log/suricata/*.json 51 | Parser suricata 52 | Db /var/log/flb_suricata.db 53 | Db.sync full 54 | Buffer_Max_Size 5MB 55 | Refresh_Interval 10 56 | 57 | output.conf: | 58 | # Systemd to Fluentd 59 | [OUTPUT] 60 | Name forward 61 | Match systemd.* 62 | Host fluentd.logging 63 | Port 24224 64 | Tag systemd.* 65 | 66 | # Kubernetes to Fluentd 67 | [OUTPUT] 68 | Name forward 69 | Match kube.* 70 | Host fluentd.logging 71 | Port 24224 72 | Tag kube.* 73 | 74 | # Suricata to Fluentd 75 | [OUTPUT] 76 | Name forward 77 | Match eve_json* 78 | Host fluentd.logging 79 | Port 24224 80 | # Shared_Key secret 81 | # Self_Hostname flb.local 82 | # tls off 83 | # tls.verify off 84 | 85 | filter-kubernetes.conf: | 86 | [FILTER] 87 | Name kubernetes 88 | Match kube.* 89 | Kube_URL https://kubernetes.default.svc:443 90 | Kube_CA_File /var/run/secrets/kubernetes.io/serviceaccount/ca.crt 91 | Kube_Token_File /var/run/secrets/kubernetes.io/serviceaccount/token 92 | Kube_Tag_Prefix kube.var.log.containers. 93 | Merge_Log On 94 | Merge_Log_Key log_processed 95 | K8S-Logging.Parser On 96 | K8S-Logging.Exclude Off 97 | 98 | filter-suricata.conf: | 99 | [FILTER] 100 | Name modify 101 | Match eve_json 102 | Condition Key_Value_Does_Not_Match src_ip 192.168.** 103 | Condition Key_Value_Does_Not_Match src_ip 172.(1[6-9]|2[0-9]|3[0-1]).** 104 | Condition Key_Value_Does_Not_Match src_ip 10.** 105 | Copy src_ip ip 106 | 107 | [FILTER] 108 | Name modify 109 | Match eve_json 110 | Condition Key_Value_Does_Not_Match dest_ip 192.168.** 111 | Condition Key_Value_Does_Not_Match dest_ip 172.(1[6-9]|2[0-9]|3[0-1]).** 112 | Condition Key_Value_Does_Not_Match dest_ip 10.** 113 | Copy dest_ip ip 114 | 115 | [FILTER] 116 | Name modify 117 | Match eve_json 118 | Condition Key_Value_Matches src_ip 192.168.** 119 | Condition Key_Value_Matches dest_ip 192.168.** 120 | 121 | Condition Key_Value_Matches src_ip 172.(1[6-9]|2[0-9]|3[0-1]).** 122 | Condition Key_Value_Matches src_ip 10.** 123 | Condition Key_Value_Matches dest_ip 192.168.178.* 124 | Condition Key_Value_Matches src_ip 192.168.178.* 125 | Add ip 80.100.143.31 126 | 127 | [FILTER] 128 | Name modify 129 | Match eve_json 130 | Condition Key_Value_Matches src_ip 172.(1[6-9]|2[0-9]|3[0-1]).** 131 | Condition Key_Value_Matches dest_ip 172.(1[6-9]|2[0-9]|3[0-1]).** 132 | Add ip 80.100.143.31 133 | 134 | [FILTER] 135 | Name modify 136 | Match eve_json 137 | Condition Key_Value_Matches src_ip 10.** 138 | Condition Key_Value_Matches dest_ip 10.** 139 | Add ip 80.100.143.31 140 | 141 | [FILTER] 142 | Name modify 143 | Match eve_json 144 | Condition Key_Value_Matches src_ip 192.168.** 145 | Condition Key_Value_Matches dest_ip 10.** 146 | Add ip 80.100.143.31 147 | 148 | [FILTER] 149 | Name modify 150 | Match eve_json 151 | Condition Key_Value_Matches src_ip 10.** 152 | Condition Key_Value_Matches dest_ip 192.168.** 153 | Add ip 80.100.143.31 154 | 155 | # [FILTER] 156 | # Name geoip2 157 | # Database /usr/share/GeoIP/GeoLite2-City.mmdb 158 | # Match eve_json 159 | # Lookup_key geoip 160 | # Record lon ip %{location.longitude} 161 | # Record lat ip %{location.latitude} 162 | # Record country_name ip %{country.names.en} 163 | # Record city_name ip %{city.names.en} 164 | # Record region_code ip %{postal.code} 165 | # Record timezone ip %{location.time_zone} 166 | # Record country_code3 ip %{country.iso_code} 167 | # Record region_name ip %{subdivisions.0.iso_code} 168 | # Record latitude ip %{location.latitude} 169 | # Record longitude ip %{location.longitude} 170 | # Record continent_code ip %{continent.code} 171 | # Record country_code2 ip %{country.iso_code} 172 | # 173 | # [FILTER] 174 | # Name nest 175 | # Match eve_json 176 | # Operation nest 177 | # Wildcard country 178 | # Wildcard lon 179 | # Wildcard lat 180 | # Nest_under location 181 | # 182 | # [FILTER] 183 | # Name nest 184 | # Match eve_json 185 | # Operation nest 186 | # Wildcard country_name 187 | # Wildcard city_name 188 | # Wildcard region_code 189 | # Wildcard timezone 190 | # Wildcard country_code3 191 | # Wildcard region_name 192 | # Wildcard ip 193 | # Wildcard latitude 194 | # Wildcard longitude 195 | # Wildcard continent_code 196 | # Wildcard country_code2 197 | # Wildcard location 198 | # Nest_under geoip 199 | 200 | [FILTER] 201 | Name modify 202 | Match eve_json 203 | Condition Key_value_equals event_type stats 204 | Hard_rename $type['eve_json'] $type['eve_json_stats'] 205 | 206 | parsers.conf: | 207 | [PARSER] 208 | Name apache 209 | Format regex 210 | Regex ^(?<host>[^ ]*) [^ ]* (?<user>[^ ]*) \[(?<time>[^\]]*)\] "(?<method>\S+)(?: +(?<path>[^\"]*?)(?: +\S*)?)?" (?<code>[^ ]*) (?<size>[^ ]*)(?: "(?<referer>[^\"]*)" "(?<agent>[^\"]*)")?$ 211 | Time_Key time 212 | Time_Format %d/%b/%Y:%H:%M:%S %z 213 | 214 | [PARSER] 215 | Name apache2 216 | Format regex 217 | Regex ^(?<host>[^ ]*) [^ ]* (?<user>[^ ]*) \[(?<time>[^\]]*)\] "(?<method>\S+)(?: +(?<path>[^ ]*) +\S*)?" (?<code>[^ ]*) (?<size>[^ ]*)(?: "(?<referer>[^\"]*)" "(?<agent>[^\"]*)")?$ 218 | Time_Key time 219 | Time_Format %d/%b/%Y:%H:%M:%S %z 220 | 221 | [PARSER] 222 | Name apache_error 223 | Format regex 224 | Regex ^\[[^ ]* (?<time>[^\]]*)\] \[(?<level>[^\]]*)\](?: \[pid (?<pid>[^\]]*)\])?( \[client (?<client>[^\]]*)\])? (?<message>.*)$ 225 | 226 | [PARSER] 227 | Name nginx 228 | Format regex 229 | Regex ^(?<remote>[^ ]*) (?<host>[^ ]*) (?<user>[^ ]*) \[(?<time>[^\]]*)\] "(?<method>\S+)(?: +(?<path>[^\"]*?)(?: +\S*)?)?" (?<code>[^ ]*) (?<size>[^ ]*)(?: "(?<referer>[^\"]*)" "(?<agent>[^\"]*)")?$ 230 | Time_Key time 231 | Time_Format %d/%b/%Y:%H:%M:%S %z 232 | 233 | [PARSER] 234 | Name json 235 | Format json 236 | Time_Key time 237 | Time_Format %d/%b/%Y:%H:%M:%S %z 238 | 239 | [PARSER] 240 | Name docker 241 | Format json 242 | Time_Key time 243 | Time_Format %Y-%m-%dT%H:%M:%S.%L 244 | Time_Keep On 245 | 246 | [PARSER] 247 | # http://rubular.com/r/tjUt3Awgg4 248 | Name cri 249 | Format regex 250 | Regex ^(?<time>[^ ]+) (?<stream>stdout|stderr) (?<logtag>[^ ]*) (?<message>.*)$ 251 | Time_Key time 252 | Time_Format %Y-%m-%dT%H:%M:%S.%L%z 253 | 254 | [PARSER] 255 | Name syslog 256 | Format regex 257 | Regex ^\<(?<pri>[0-9]+)\>(?<time>[^ ]* {1,2}[^ ]* [^ ]*) (?<host>[^ ]*) (?<ident>[a-zA-Z0-9_\/\.\-]*)(?:\[(?<pid>[0-9]+)\])?(?:[^\:]*\:)? *(?<message>.*)$ 258 | Time_Key time 259 | Time_Format %b %d %H:%M:%S 260 | 261 | [PARSER] 262 | Name suricata 263 | Format json 264 | Time_Key timestamp 265 | Time_Format %Y-%m-%dT%H:%M:%S.%L%z 266 | -------------------------------------------------------------------------------- /kubernetes/fluentd_fluent-bit/fluentbit-daemonset.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | apiVersion: v1 4 | kind: ServiceAccount 5 | metadata: 6 | name: fluent-bit 7 | namespace: suricata 8 | labels: 9 | app: fluent-bit 10 | 11 | --- 12 | 13 | apiVersion: rbac.authorization.k8s.io/v1 14 | kind: ClusterRole 15 | metadata: 16 | name: fluent-bit 17 | labels: 18 | app: fluent-bit 19 | rules: 20 | - apiGroups: 21 | - "" 22 | resources: 23 | - namespaces 24 | - pods 25 | verbs: 26 | - get 27 | - list 28 | - watch 29 | --- 30 | 31 | apiVersion: rbac.authorization.k8s.io/v1 32 | kind: ClusterRoleBinding 33 | metadata: 34 | name: fluent-bit 35 | labels: 36 | app: fluent-bit 37 | roleRef: 38 | apiGroup: rbac.authorization.k8s.io 39 | kind: ClusterRole 40 | name: fluent-bit 41 | subjects: 42 | - kind: ServiceAccount 43 | name: fluent-bit 44 | namespace: suricata 45 | 46 | --- 47 | apiVersion: apps/v1 48 | kind: DaemonSet 49 | metadata: 50 | name: fluent-bit 51 | namespace: suricata 52 | labels: 53 | app: fluent-bit 54 | kubernetes.io/cluster-service: "true" 55 | annotations: 56 | keel.sh/policy: minor 57 | keel.sh/trigger: poll 58 | spec: 59 | selector: 60 | matchLabels: 61 | app: fluent-bit 62 | template: 63 | metadata: 64 | labels: 65 | app: fluent-bit 66 | kubernetes.io/cluster-service: "true" 67 | annotations: 68 | prometheus.io/scrape: "true" 69 | prometheus.io/port: "2020" 70 | prometheus.io/path: /api/v1/metrics/prometheus 71 | spec: 72 | serviceAccountName: fluent-bit 73 | containers: 74 | - name: fluent-bit 75 | image: fluent/fluent-bit:1.9.1 76 | 77 | ports: 78 | - name: http 79 | containerPort: 2020 80 | protocol: TCP 81 | 82 | livenessProbe: 83 | httpGet: 84 | path: /api/v1/health 85 | port: http 86 | readinessProbe: 87 | httpGet: 88 | path: /api/v1/health 89 | port: http 90 | 91 | resources: 92 | limits: 93 | cpu: 100m 94 | memory: 100Mi 95 | requests: 96 | cpu: 100m 97 | memory: 50Mi 98 | 99 | securityContext: 100 | privileged: false 101 | runAsUser: 0 102 | 103 | volumeMounts: 104 | - name: var-log 105 | mountPath: /var/log 106 | - name: suricata-log 107 | mountPath: /var/log/suricata 108 | readOnly: True 109 | 110 | - name: var-lib-containers 111 | mountPath: /var/lib/containers 112 | readOnly: true 113 | 114 | - name: fluent-bit-config 115 | mountPath: /fluent-bit/etc/ 116 | 117 | - name: etcmachineid 118 | mountPath: /etc/machine-id 119 | readOnly: true 120 | 121 | terminationGracePeriodSeconds: 10 122 | volumes: 123 | - name: var-log 124 | hostPath: 125 | path: /var/log 126 | - name: suricata-log 127 | persistentVolumeClaim: 128 | claimName: suricata-log 129 | readOnly: true 130 | 131 | - name: var-lib-containers 132 | hostPath: 133 | path: /var/lib/containers 134 | 135 | - name: fluent-bit-config 136 | configMap: 137 | name: fluent-bit-config 138 | 139 | - name: etcmachineid 140 | hostPath: 141 | path: /etc/machine-id 142 | type: File 143 | 144 | nodeSelector: 145 | kubernetes.io/os: linux 146 | 147 | # serviceAccountName: fluent-bit 148 | tolerations: 149 | - key: node-role.kubernetes.io/master 150 | operator: Exists 151 | effect: NoSchedule 152 | - operator: "Exists" 153 | effect: "NoExecute" 154 | - operator: "Exists" 155 | effect: "NoSchedule" 156 | -------------------------------------------------------------------------------- /kubernetes/fluentd_fluent-bit/fluentbit-service.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | apiVersion: v1 4 | kind: Service 5 | metadata: 6 | name: fluent-bit 7 | namespace: logging 8 | labels: 9 | app: fluent-bit 10 | spec: 11 | type: ClusterIP 12 | ports: 13 | - port: 2020 14 | protocol: TCP 15 | name: fluent-bit 16 | targetPort: 2020 17 | selector: 18 | app: fluent-bit 19 | -------------------------------------------------------------------------------- /kubernetes/fluentd_fluent-bit/fluentd-deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: fluentd 5 | namespace: logging 6 | labels: 7 | app: fluentd 8 | spec: 9 | replicas: 1 10 | selector: 11 | matchLabels: 12 | app: fluentd 13 | template: 14 | metadata: 15 | labels: 16 | app: fluentd 17 | spec: 18 | automountServiceAccountToken: false 19 | 20 | initContainers: 21 | - name: configure-sysctl 22 | securityContext: 23 | runAsUser: 0 24 | privileged: true 25 | image: "docker.io/bitnami/minideb:buster" 26 | imagePullPolicy: "IfNotPresent" 27 | command: ["bash","-c"] 28 | args: 29 | - | 30 | set -o errexit 31 | set -o pipefail 32 | set -o nounset 33 | 34 | if ! [ -x "$(command -v sysctl)" ]; then 35 | echo 'sysctl not installed. Installing it...' 36 | distro=$(awk -F= '/^ID=/{print $2}' /etc/os-release | tr -d '"') 37 | case $distro in 38 | ol | centos) 39 | yum install -y procps 40 | rm -rf /var/cache/yum;; 41 | ubuntu | debian) 42 | apt-get update -qq && apt-get install -y --no-install-recommends procps 43 | rm -rf /var/lib/apt/lists /var/cache/apt/archives;; 44 | esac 45 | fi 46 | 47 | sysctl -w fs.file-max=65536 48 | sysctl -w fs.protected_hardlinks=1 49 | sysctl -w fs.protected_symlinks=1 50 | 51 | containers: 52 | - name: fluentd 53 | image: fluent/fluentd-kubernetes-daemonset:v1.14.5-debian-elasticsearch7-amd64-1.1 54 | 55 | ports: 56 | - name: fluent-bit 57 | containerPort: 24224 58 | protocol: TCP 59 | - name: metrics 60 | containerPort: 24231 61 | protocol: TCP 62 | 63 | livenessProbe: 64 | httpGet: 65 | path: /metrics 66 | port: metrics 67 | readinessProbe: 68 | httpGet: 69 | path: /metrics 70 | port: metrics 71 | 72 | resources: 73 | limits: 74 | memory: 200Mi 75 | requests: 76 | cpu: 100m 77 | memory: 150Mi 78 | 79 | securityContext: 80 | allowPrivilegeEscalation: false 81 | capabilities: 82 | drop: 83 | - ALL 84 | privileged: false 85 | readOnlyRootFilesystem: false 86 | seccompProfile: 87 | type: RuntimeDefault 88 | 89 | volumeMounts: 90 | - name: fluentd-config 91 | mountPath: /fluentd/etc/ 92 | readOnly: True 93 | 94 | terminationGracePeriodSeconds: 30 95 | volumes: 96 | - name: fluentd-config 97 | configMap: 98 | name: fluentd-config 99 | -------------------------------------------------------------------------------- /kubernetes/fluentd_fluent-bit/fluentd-service.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | apiVersion: v1 4 | kind: Service 5 | metadata: 6 | name: fluentd 7 | namespace: logging 8 | labels: 9 | app: fluentd 10 | spec: 11 | type: ClusterIP 12 | ports: 13 | - port: 24224 14 | protocol: TCP 15 | name: fluentd 16 | targetPort: 24224 17 | selector: 18 | app: fluentd 19 | -------------------------------------------------------------------------------- /kubernetes/install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | kubectl create --save-config -f common/storageclass.yaml 4 | kubectl create --save-config -f common/suricata-ns.yaml 5 | kubectl create --save-config -f common/logging-ns.yaml 6 | 7 | kubectl create --save-config -f elasticsearch/elasticsearch-pv.yaml 8 | kubectl create --save-config -f elasticsearch/elasticsearch-pvc.yaml 9 | kubectl create --save-config -f elasticsearch/elasticsearch-statefulset.yaml 10 | kubectl create --save-config -f elasticsearch/elasticsearch-service.yaml 11 | 12 | kubectl create --save-config -f suricata/suricata-pv.yaml 13 | kubectl create --save-config -f suricata/suricata-pvc.yaml 14 | kubectl create --save-config -f suricata/suricata-configmap.yaml 15 | kubectl create --save-config -f suricata/suricata-daemonset.yaml 16 | kubectl create --save-config -f suricata/suricata-cronjob.yaml 17 | 18 | # If you'd like to use Logstash with Filebeat (mutually exclusive with Fluentd with Fuent-bit) 19 | kubectl create --save-config -f logstash_filebeat/logstash-configmap.yaml 20 | kubectl create --save-config -f logstash_filebeat/logstash-statefulset.yaml 21 | kubectl create --save-config -f logstash_filebeat/logstash-service.yaml 22 | kubectl create --save-config -f logstash_filebeat/filebeat-configmap.yaml 23 | kubectl create --save-config -f logstash_filebeat/filebeat-daemonset.yaml 24 | 25 | # If you'd like to use Fluentd with Fluent-bit (mutually exclusive with Logstash with Filebeat) 26 | # kubectl create --save-config -f fluentd_fluent-bit/fluentd-configmap.yaml 27 | # kubectl create --save-config -f fluentd_fluent-bit/fluentd-deployment.yaml 28 | # kubectl create --save-config -f fluentd_fluent-bit/fluentd-service.yaml 29 | # kubectl create --save-config -f fluentd_fluent-bit/fluentbit-configmap.yaml 30 | # kubectl create --save-config -f fluentd_fluent-bit/fluentbit-daemonset.yaml 31 | # kubectl create --save-config -f fluentd_fluent-bit/fluentbit-service.yaml 32 | 33 | kubectl create --save-config -f evebox/evebox-deployment.yaml 34 | kubectl create --save-config -f evebox/evebox-service.yaml 35 | 36 | kubectl create --save-config -f kibana/kibana-deployment.yaml 37 | kubectl create --save-config -f kibana/kibana-service.yaml 38 | 39 | kubectl create --save-config -f scirius/scirius-pv.yaml 40 | kubectl create --save-config -f scirius/scirius-pvc.yaml 41 | kubectl create --save-config -f scirius/scirius-secret.yaml 42 | kubectl create --save-config -f scirius/scirius-deployment.yaml 43 | kubectl create --save-config -f scirius/scirius-service.yaml 44 | 45 | kubectl create --save-config -f arkime/arkime-pv.yaml 46 | kubectl create --save-config -f arkime/arkime-pvc.yaml 47 | kubectl create --save-config -f arkime/arkime-secret.yaml 48 | kubectl create --save-config -f arkime/arkime-configmap.yaml 49 | kubectl create --save-config -f arkime/arkime-deployment.yaml 50 | 51 | # For a regular NGINX installation 52 | kubectl create --save-config -f nginx/nginx-secret.yaml 53 | kubectl create --save-config -f nginx/nginx-configmap.yaml 54 | kubectl create --save-config -f nginx/nginx-deployment.yaml 55 | kubectl create --save-config -f nginx/nginx-service.yaml 56 | kubectl create --save-config -f nginx/nginx-ingress.yaml 57 | 58 | # For a NGINX installation hardened with OWASP mod-security 59 | # kubectl create --save-config -f nginx/nginx-secret.yaml 60 | # kubectl create --save-config -f nginx/nginx-owasp-configmap.yaml 61 | # kubectl create --save-config -f nginx/nginx-owasp-deployment.yaml 62 | # kubectl create --save-config -f nginx/nginx-owasp-service.yaml 63 | # kubectl create --save-config -f nginx/nginx-ingress.yaml 64 | -------------------------------------------------------------------------------- /kubernetes/kibana/kibana-dashboards-job.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: batch/v1 2 | kind: Job 3 | metadata: 4 | labels: 5 | app: kibana-dashboards-job 6 | name: kibana-dashboards-job 7 | namespace: logging 8 | spec: 9 | template: 10 | spec: 11 | restartPolicy: Never 12 | containers: 13 | - image: alpine 14 | name: kibana-dashboards-job 15 | command: ["sh","-c"] 16 | args: 17 | - | 18 | apk add git curl 19 | git clone https://github.com/StamusNetworks/KTS7.git 20 | cd KTS7/API-KIBANA7 21 | curl -X POST "kibana:5601/api/saved_objects/_import?overwrite=true" -H 'kbn-xsrf: true' --form file=@index-pattern.ndjson 22 | curl -X POST "kibana:5601/api/saved_objects/_import?overwrite=true" -H 'kbn-xsrf: true' --form file=@search.ndjson 23 | curl -X POST "kibana:5601/api/saved_objects/_import?overwrite=true" -H 'kbn-xsrf: true' --form file=@visualization.ndjson 24 | curl -X POST "kibana:5601/api/saved_objects/_import?overwrite=true" -H 'kbn-xsrf: true' --form file=@dashboard.ndjson 25 | curl -X POST "kibana:5601/api/saved_objects/_import?overwrite=true" -H 'kbn-xsrf: true' --form file=@query.ndjson 26 | 27 | securityContext: 28 | allowPrivilegeEscalation: false 29 | capabilities: 30 | drop: 31 | - ALL 32 | privileged: false 33 | runAsGroup: 1000 34 | runAsUser: 0 35 | seccompProfile: 36 | type: RuntimeDefault 37 | -------------------------------------------------------------------------------- /kubernetes/kibana/kibana-deployment.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | apiVersion: apps/v1 4 | kind: Deployment 5 | metadata: 6 | annotations: 7 | labels: 8 | app: kibana 9 | name: kibana 10 | namespace: logging 11 | spec: 12 | replicas: 1 13 | selector: 14 | matchLabels: 15 | app: kibana 16 | template: 17 | metadata: 18 | annotations: 19 | fluentbit.io/exclude: "true" 20 | labels: 21 | app: kibana 22 | spec: 23 | automountServiceAccountToken: false 24 | 25 | securityContext: 26 | fsGroup: 1000 27 | containers: 28 | - name: kibana 29 | image: "docker.elastic.co/kibana/kibana:7.16.3" 30 | 31 | env: 32 | - name: SERVER_PUBLICBASEURL 33 | value: "http://localhost:5601" 34 | - name: ELASTICSEARCH_HOSTS 35 | value: "http://elasticsearch:9200" 36 | - name: SERVER_HOST 37 | value: "0.0.0.0" 38 | - name: NODE_OPTIONS 39 | value: --max-old-space-size=1800 40 | - name: LOGGING_ROOT_LEVEL 41 | value: "warn" 42 | 43 | ports: 44 | - containerPort: 5601 45 | 46 | readinessProbe: 47 | failureThreshold: 3 48 | initialDelaySeconds: 10 49 | periodSeconds: 10 50 | successThreshold: 3 51 | timeoutSeconds: 5 52 | exec: 53 | command: 54 | - sh 55 | - -c 56 | - | 57 | #!/usr/bin/env bash -e 58 | 59 | # Disable nss cache to avoid filling dentry cache when calling curl 60 | # This is required with Kibana Docker using nss < 3.52 61 | export NSS_SDB_USE_CACHE=no 62 | 63 | http () { 64 | local path="${1}" 65 | set -- -XGET -s --fail -L 66 | 67 | if [ -n "${ELASTICSEARCH_USERNAME}" ] && [ -n "${ELASTICSEARCH_PASSWORD}" ]; then 68 | set -- "$@" -u "${ELASTICSEARCH_USERNAME}:${ELASTICSEARCH_PASSWORD}" 69 | fi 70 | 71 | STATUS=$(curl --output /dev/null --write-out "%{http_code}" -k "$@" "http://localhost:5601${path}") 72 | if [[ "${STATUS}" -eq 200 ]]; then 73 | exit 0 74 | fi 75 | 76 | echo "Error: Got HTTP code ${STATUS} but expected a 200" 77 | exit 1 78 | } 79 | 80 | http "/app/kibana" 81 | livenessProbe: 82 | failureThreshold: 3 83 | initialDelaySeconds: 10 84 | periodSeconds: 10 85 | timeoutSeconds: 5 86 | exec: 87 | command: 88 | - sh 89 | - -c 90 | - | 91 | #!/usr/bin/env bash -e 92 | 93 | # Disable nss cache to avoid filling dentry cache when calling curl 94 | # This is required with Kibana Docker using nss < 3.52 95 | export NSS_SDB_USE_CACHE=no 96 | 97 | http () { 98 | local path="${1}" 99 | set -- -XGET -s --fail -L 100 | 101 | if [ -n "${ELASTICSEARCH_USERNAME}" ] && [ -n "${ELASTICSEARCH_PASSWORD}" ]; then 102 | set -- "$@" -u "${ELASTICSEARCH_USERNAME}:${ELASTICSEARCH_PASSWORD}" 103 | fi 104 | 105 | STATUS=$(curl --output /dev/null --write-out "%{http_code}" -k "$@" "http://localhost:5601${path}") 106 | if [[ "${STATUS}" -eq 200 ]]; then 107 | exit 0 108 | fi 109 | 110 | echo "Error: Got HTTP code ${STATUS} but expected a 200" 111 | exit 1 112 | } 113 | 114 | http "/app/kibana" 115 | 116 | resources: 117 | limits: 118 | cpu: 200m 119 | memory: 1Gi 120 | requests: 121 | cpu: 100m 122 | memory: 500Mi 123 | 124 | securityContext: 125 | allowPrivilegeEscalation: false 126 | capabilities: 127 | drop: 128 | - ALL 129 | privileged: false 130 | runAsGroup: 1000 131 | runAsNonRoot: true 132 | runAsUser: 1000 133 | seccompProfile: 134 | type: RuntimeDefault 135 | restartPolicy: Always 136 | -------------------------------------------------------------------------------- /kubernetes/kibana/kibana-service.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | apiVersion: v1 4 | kind: Service 5 | metadata: 6 | name: kibana 7 | namespace: logging 8 | labels: 9 | app: kibana 10 | spec: 11 | type: ClusterIP 12 | ports: 13 | - port: 5601 14 | protocol: TCP 15 | name: http 16 | targetPort: 5601 17 | selector: 18 | app: kibana 19 | -------------------------------------------------------------------------------- /kubernetes/logstash_filebeat/filebeat-configmap.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | apiVersion: v1 4 | kind: ConfigMap 5 | metadata: 6 | name: filebeat-config 7 | namespace: suricata 8 | labels: 9 | app: filebeat 10 | data: 11 | filebeat.yml: |- 12 | filebeat.inputs: 13 | - type: filestream 14 | paths: 15 | - /var/log/suricata/*.json 16 | json.keys_under_root: true 17 | 18 | processors: 19 | - add_fields: 20 | target: '' 21 | fields: 22 | type: "SELKS" 23 | 24 | output.logstash: 25 | enabled: true 26 | host: '${NODE_NAME}' 27 | hosts: ["logstash.logging.svc.cluster.local:5044"] 28 | worker: 1 29 | -------------------------------------------------------------------------------- /kubernetes/logstash_filebeat/filebeat-daemonset.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | apiVersion: v1 4 | kind: ServiceAccount 5 | metadata: 6 | name: filebeat 7 | namespace: suricata 8 | labels: 9 | app: filebeat 10 | 11 | --- 12 | apiVersion: apps/v1 13 | kind: DaemonSet 14 | metadata: 15 | name: filebeat 16 | namespace: suricata 17 | labels: 18 | app: filebeat 19 | spec: 20 | selector: 21 | matchLabels: 22 | app: filebeat 23 | template: 24 | metadata: 25 | labels: 26 | app: filebeat 27 | spec: 28 | tolerations: 29 | - key: node-role.kubernetes.io/master 30 | effect: NoSchedule 31 | serviceAccountName: filebeat 32 | terminationGracePeriodSeconds: 30 33 | 34 | containers: 35 | - name: filebeat 36 | image: "docker.elastic.co/beats/filebeat:7.17.9" 37 | args: 38 | - "-e" 39 | - "-E" 40 | - "http.enabled=true" 41 | 42 | env: 43 | - name: POD_NAMESPACE 44 | valueFrom: 45 | fieldRef: 46 | fieldPath: metadata.namespace 47 | - name: NODE_NAME 48 | valueFrom: 49 | fieldRef: 50 | fieldPath: spec.nodeName 51 | 52 | livenessProbe: 53 | exec: 54 | command: 55 | - sh 56 | - -c 57 | - | 58 | #!/usr/bin/env bash -e 59 | curl --fail 127.0.0.1:5066 60 | failureThreshold: 3 61 | initialDelaySeconds: 10 62 | periodSeconds: 10 63 | timeoutSeconds: 5 64 | readinessProbe: 65 | exec: 66 | command: 67 | - sh 68 | - -c 69 | - | 70 | #!/usr/bin/env bash -e 71 | filebeat test output 72 | failureThreshold: 3 73 | initialDelaySeconds: 10 74 | periodSeconds: 10 75 | timeoutSeconds: 5 76 | 77 | resources: 78 | limits: 79 | cpu: 1000m 80 | memory: 200Mi 81 | requests: 82 | cpu: 100m 83 | memory: 100Mi 84 | 85 | securityContext: 86 | allowPrivilegeEscalation: false 87 | capabilities: 88 | drop: 89 | - ALL 90 | privileged: false 91 | runAsUser: 10000 92 | runAsGroup: 0 93 | 94 | volumeMounts: 95 | - name: filebeat-config 96 | mountPath: /usr/share/filebeat/filebeat.yml 97 | readOnly: true 98 | subPath: filebeat.yml 99 | 100 | - name: data 101 | mountPath: /usr/share/filebeat/data 102 | 103 | - mountPath: /var/log/suricata 104 | name: suricata-log 105 | readOnly: True 106 | 107 | nodeSelector: 108 | kubernetes.io/os: linux 109 | 110 | volumes: 111 | - name: filebeat-config 112 | configMap: 113 | defaultMode: 0644 114 | name: filebeat-config 115 | 116 | - name: suricata-log 117 | persistentVolumeClaim: 118 | claimName: suricata-log 119 | readOnly: true 120 | 121 | - name: data 122 | hostPath: 123 | path: /var/lib/filebeat-data 124 | type: DirectoryOrCreate 125 | -------------------------------------------------------------------------------- /kubernetes/logstash_filebeat/logstash-configmap.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: logstash-configmap 5 | namespace: logging 6 | data: 7 | logstash.conf: | 8 | input { 9 | beats { 10 | port => 5044 11 | type => "SELKS" 12 | codec => "json" 13 | } 14 | } 15 | 16 | filter { 17 | if [type] == "SELKS" { 18 | 19 | date { 20 | match => [ "timestamp", "ISO8601" ] 21 | } 22 | 23 | ruby { 24 | code => " 25 | if event.get('[event_type]') == 'fileinfo' 26 | event.set('[fileinfo][type]', event.get('[fileinfo][magic]').to_s.split(',')[0]) 27 | end 28 | " 29 | } 30 | ruby { 31 | code => " 32 | if event.get('[event_type]') == 'alert' 33 | sp = event.get('[alert][signature]').to_s.split(' group ') 34 | if (sp.length == 2) and /\A\d+\z/.match(sp[1]) 35 | event.set('[alert][signature]', sp[0]) 36 | end 37 | end 38 | " 39 | } 40 | 41 | # Counter for eve_insert 42 | metrics { 43 | meter => [ "eve_insert" ] 44 | add_tag => "metric" 45 | flush_interval => 30 46 | } 47 | } 48 | 49 | if [http] { 50 | useragent { 51 | source => "[http][http_user_agent]" 52 | target => "[http][user_agent]" 53 | } 54 | } 55 | if [src_ip] { 56 | geoip { 57 | source => "src_ip" 58 | target => "geoip" 59 | #database => "/opt/logstash/vendor/geoip/GeoLiteCity.dat" 60 | #add_field => [ "[geoip][coordinates]", "%{[geoip][longitude]}" ] 61 | #add_field => [ "[geoip][coordinates]", "%{[geoip][latitude]}" ] 62 | } 63 | } 64 | if [dest_ip] { 65 | geoip { 66 | source => "dest_ip" 67 | target => "geoip" 68 | #database => "/opt/logstash/vendor/geoip/GeoLiteCity.dat" 69 | #add_field => [ "[geoip][coordinates]", "%{[geoip][longitude]}" ] 70 | #add_field => [ "[geoip][coordinates]", "%{[geoip][latitude]}" ] 71 | } 72 | } 73 | } 74 | 75 | output { 76 | if [event_type] and [event_type] != 'stats' { 77 | elasticsearch { 78 | hosts => "elasticsearch" 79 | index => "logstash-%{event_type}-%{+YYYY.MM.dd}" 80 | template_overwrite => true 81 | template => "/usr/share/logstash/config/elasticsearch7-template.json" 82 | } 83 | } else { 84 | elasticsearch { 85 | hosts => "elasticsearch" 86 | index => "logstash-%{+YYYY.MM.dd}" 87 | template_overwrite => true 88 | template => "/usr/share/logstash/config/elasticsearch7-template.json" 89 | } 90 | } 91 | } 92 | 93 | elasticsearch7-template.json: | 94 | { 95 | "template" : "logstash-*", 96 | "order": 1, 97 | "version" : 70002, 98 | "index_patterns": [ 99 | "logstash-*" 100 | ], 101 | "settings" : { 102 | "index": { 103 | "number_of_replicas": 0, 104 | "refresh_interval" : "5s", 105 | "mapping.total_fields.limit": 10000 106 | }, 107 | "analysis": { 108 | "analyzer": { 109 | "sn_analyzer": { 110 | "type": "custom", 111 | "tokenizer": "whitespace", 112 | "char_filter": [ 113 | "sn_lowercase" 114 | ] 115 | } 116 | }, 117 | "char_filter": { 118 | "sn_lowercase": { 119 | "type": "mapping", 120 | "mappings": [ 121 | "A => a", "B => b", "C => c", "D => d", "E => e", "F => f", "G => g", "H => h", "I => i", "J => j", "K => k", "L => l", "M => m", "N => n", "O => o", "P => p", "Q => q", "R => r", "S => s", "T => t", "U => u", "V => v", "W => w", "X => x", "Y => y", "Z => z" ] 122 | } 123 | } 124 | } 125 | }, 126 | "mappings" : { 127 | "dynamic_templates" : [ { 128 | "message_field" : { 129 | "path_match" : "message", 130 | "match_mapping_type" : "string", 131 | "mapping" : { 132 | "type" : "text", 133 | "norms" : false, 134 | "analyzer": "sn_analyzer", 135 | "search_analyzer":"sn_analyzer", 136 | "search_quote_analyzer":"sn_analyzer" 137 | } 138 | } 139 | }, { 140 | "string_fields" : { 141 | "match" : "*", 142 | "match_mapping_type" : "string", 143 | "mapping" : { 144 | "type" : "text", "norms" : false, 145 | "analyzer": "sn_analyzer", 146 | "search_analyzer":"sn_analyzer", 147 | "search_quote_analyzer":"sn_analyzer", 148 | "fields" : { 149 | "keyword" : { "type": "keyword", "ignore_above": 256 }, 150 | "raw" : { "type": "keyword", "ignore_above": 256 } 151 | } 152 | } 153 | } 154 | }, { 155 | "percentage_fields_long_to_float": { 156 | "path_match": "*.pct", 157 | "match_mapping_type": "long", 158 | "mapping": { 159 | "type": "float" 160 | } 161 | } 162 | } ], 163 | "properties" : { 164 | "@timestamp": { "type": "date" }, 165 | "@version": { "type": "keyword" }, 166 | "geoip" : { 167 | "dynamic": true, 168 | "properties" : { 169 | "ip": { "type": "ip" }, 170 | "location" : { "type" : "geo_point" }, 171 | "latitude" : { "type" : "half_float" }, 172 | "longitude" : { "type" : "half_float" } 173 | } 174 | }, 175 | "discovery" : { 176 | "dynamic": true, 177 | "properties" : { 178 | "asset": { 179 | "type": "ip", 180 | "fields": { 181 | "raw": {"type": "keyword"}, 182 | "keyword": {"type": "keyword"} 183 | } 184 | } 185 | } 186 | }, 187 | "dest_ip": { 188 | "type": "ip", 189 | "fields": { 190 | "raw": {"type": "keyword"}, 191 | "keyword": {"type": "keyword"} 192 | } 193 | }, 194 | "src_ip": { 195 | "type": "ip", 196 | "fields": { 197 | "raw": {"type": "keyword"}, 198 | "keyword": {"type": "keyword"} 199 | } 200 | }, 201 | "cpu": { 202 | "properties": { 203 | "system_p": { 204 | "doc_values": "true", 205 | "type": "float" 206 | }, 207 | "user_p": { 208 | "doc_values": "true", 209 | "type": "float" 210 | } 211 | } 212 | }, 213 | "fs": { 214 | "properties": { 215 | "used_p": { 216 | "doc_values": "true", 217 | "type": "float" 218 | } 219 | } 220 | }, 221 | "load": { 222 | "properties": { 223 | "load1": { 224 | "doc_values": "true", 225 | "type": "float" 226 | }, 227 | "load15": { 228 | "doc_values": "true", 229 | "type": "float" 230 | }, 231 | "load5": { 232 | "doc_values": "true", 233 | "type": "float" 234 | } 235 | } 236 | }, 237 | "mem": { 238 | "properties": { 239 | "actual_used_p": { 240 | "doc_values": "true", 241 | "type": "float" 242 | }, 243 | "used_p": { 244 | "doc_values": "true", 245 | "type": "float" 246 | } 247 | } 248 | }, 249 | "proc": { 250 | "properties": { 251 | "cpu": { 252 | "properties": { 253 | "user_p": { 254 | "doc_values": "true", 255 | "type": "float" 256 | } 257 | } 258 | }, 259 | "mem": { 260 | "properties": { 261 | "rss_p": { 262 | "doc_values": "true", 263 | "type": "float" 264 | } 265 | } 266 | } 267 | } 268 | }, 269 | "swap": { 270 | "properties": { 271 | "used_p": { 272 | "doc_values": "true", 273 | "type": "float" 274 | } 275 | } 276 | }, 277 | "ip": { 278 | "type": "ip" 279 | }, 280 | "alert": { 281 | "properties": { 282 | "source": { 283 | "properties": { 284 | "ip": { 285 | "type": "ip", 286 | "fields": { 287 | "keyword": {"type": "keyword"} 288 | } 289 | } 290 | } 291 | }, 292 | "target": { 293 | "properties": { 294 | "ip": { 295 | "type": "ip", 296 | "fields": { 297 | "keyword": {"type": "keyword"} 298 | } 299 | } 300 | } 301 | } 302 | } 303 | } 304 | } 305 | } 306 | } 307 | -------------------------------------------------------------------------------- /kubernetes/logstash_filebeat/logstash-service.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | kind: Service 4 | apiVersion: v1 5 | metadata: 6 | name: "logstash" 7 | labels: 8 | app: "logstash" 9 | namespace: logging 10 | spec: 11 | clusterIP: None 12 | selector: 13 | app: "logstash" 14 | ports: 15 | - name: http 16 | port: 9600 17 | - name: beats 18 | port: 5044 19 | -------------------------------------------------------------------------------- /kubernetes/logstash_filebeat/logstash-statefulset.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | apiVersion: apps/v1 4 | kind: StatefulSet 5 | metadata: 6 | annotations: 7 | labels: 8 | app: logstash 9 | name: logstash 10 | namespace: logging 11 | spec: 12 | replicas: 1 13 | serviceName: logstash 14 | selector: 15 | matchLabels: 16 | app: logstash 17 | updateStrategy: 18 | type: RollingUpdate 19 | template: 20 | metadata: 21 | annotations: 22 | labels: 23 | app: logstash 24 | spec: 25 | automountServiceAccountToken: false 26 | 27 | securityContext: 28 | fsGroup: 1000 29 | 30 | containers: 31 | - name: logstash 32 | image: "docker.elastic.co/logstash/logstash:7.17.9" 33 | 34 | env: 35 | - name: LS_JAVA_OPTS 36 | value: "-Xms512m -Xmx512m" 37 | 38 | securityContext: 39 | allowPrivilegeEscalation: false 40 | capabilities: 41 | drop: 42 | - ALL 43 | privileged: false 44 | runAsGroup: 1000 45 | runAsNonRoot: true 46 | runAsUser: 1000 47 | seccompProfile: 48 | type: RuntimeDefault 49 | 50 | livenessProbe: 51 | failureThreshold: 3 52 | httpGet: 53 | path: / 54 | port: http 55 | initialDelaySeconds: 300 56 | periodSeconds: 10 57 | successThreshold: 1 58 | timeoutSeconds: 5 59 | readinessProbe: 60 | failureThreshold: 3 61 | httpGet: 62 | path: / 63 | port: http 64 | initialDelaySeconds: 60 65 | periodSeconds: 10 66 | successThreshold: 3 67 | timeoutSeconds: 5 68 | 69 | ports: 70 | - name: http 71 | containerPort: 9600 72 | - name: beats 73 | containerPort: 5044 74 | 75 | resources: 76 | limits: 77 | cpu: 1000m 78 | memory: 1536Mi 79 | requests: 80 | cpu: 100m 81 | memory: 1536Mi 82 | 83 | volumeMounts: 84 | - mountPath: /usr/share/logstash/pipeline/logstash.conf 85 | name: logstash-pipeline-conf 86 | subPath: logstash.conf 87 | readOnly: True 88 | - mountPath: /usr/share/logstash/config/elasticsearch7-template.json 89 | name: logstash-elasticsearch-conf 90 | subPath: elasticsearch7-template.json 91 | readOnly: True 92 | 93 | restartPolicy: Always 94 | volumes: 95 | - name: logstash-pipeline-conf 96 | configMap: 97 | name: logstash-configmap 98 | items: 99 | - key: logstash.conf 100 | path: logstash.conf 101 | mode: 0444 102 | - name: logstash-elasticsearch-conf 103 | configMap: 104 | name: logstash-configmap 105 | items: 106 | - key: elasticsearch7-template.json 107 | path: elasticsearch7-template.json 108 | mode: 0444 109 | -------------------------------------------------------------------------------- /kubernetes/nginx/nginx-configmap.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: nginx-configmap 5 | namespace: suricata 6 | data: 7 | nginx.conf: | 8 | user nginx; 9 | worker_processes 1; 10 | # pid /var/run/nginx.pid; 11 | pid /run/nginx/nginx.pid; 12 | include /etc/nginx/modules-enabled/*.conf; 13 | 14 | events { 15 | worker_connections 768; 16 | # multi_accept on; 17 | } 18 | 19 | http { 20 | 21 | ## 22 | # Basic Settings 23 | ## 24 | 25 | sendfile on; 26 | tcp_nopush on; 27 | tcp_nodelay on; 28 | keepalive_timeout 65; 29 | types_hash_max_size 2048; 30 | client_max_body_size 20M; 31 | # server_tokens off; 32 | 33 | # server_names_hash_bucket_size 64; 34 | # server_name_in_redirect off; 35 | 36 | include /etc/nginx/mime.types; 37 | default_type application/octet-stream; 38 | 39 | ## 40 | # SSL Settings 41 | ## 42 | 43 | ssl_protocols TLSv1.2 TLSv1.3; 44 | ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384; 45 | 46 | ssl_stapling off; 47 | ssl_stapling_verify off; 48 | 49 | ssl_verify_client off; 50 | 51 | ## 52 | # Logging Settings 53 | ## 54 | 55 | log_format main '$remote_addr - $remote_user [$time_local] "$request" ' 56 | '$status $body_bytes_sent "$http_referer" ' 57 | '"$http_user_agent" "$http_x_forwarded_for"'; 58 | 59 | access_log /var/log/nginx/access.log main; 60 | access_log /dev/null combined; 61 | 62 | error_log /var/log/nginx/error.log warn; 63 | 64 | ## 65 | # Gzip Settings 66 | ## 67 | 68 | gzip on; 69 | 70 | # gzip_vary on; 71 | # gzip_proxied any; 72 | # gzip_comp_level 6; 73 | # gzip_buffers 16 8k; 74 | # gzip_http_version 1.1; 75 | # gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript; 76 | 77 | ## 78 | # Virtual Host Configs 79 | ## 80 | 81 | include /etc/nginx/conf.d/*.conf; 82 | } 83 | default.conf: | 84 | map $http_upgrade $connection_upgrade { 85 | default upgrade; 86 | '' close; 87 | } 88 | selks6.conf: | 89 | server { 90 | 91 | listen 8080; 92 | listen 8443 ssl; 93 | ssl_certificate /etc/nginx/ssl/tls.crt; 94 | ssl_certificate_key /etc/nginx/ssl/tls.key; 95 | 96 | server_name SELKS; 97 | 98 | access_log /var/log/nginx/scirius.access.log; 99 | error_log /var/log/nginx/scirius.error.log; 100 | 101 | # https://docs.djangoproject.com/en/dev/howto/static-files/#serving-static-files-in-production 102 | location /static/ { # STATIC_URL 103 | alias /static/; # STATIC_ROOT 104 | expires 30d; 105 | } 106 | 107 | location /media/ { # MEDIA_URL 108 | alias /static/; # MEDIA_ROOT 109 | expires 30d; 110 | } 111 | 112 | location /plugins/ { 113 | proxy_pass http://kibana.logging:5601/plugins/; 114 | proxy_redirect off; 115 | } 116 | 117 | location /dlls/ { 118 | proxy_pass http://kibana.logging:5601/dlls/; 119 | proxy_redirect off; 120 | } 121 | 122 | location /socket.io/ { 123 | proxy_pass http://kibana.logging:5601/socket.io/; 124 | proxy_redirect off; 125 | } 126 | 127 | location /dataset/ { 128 | proxy_pass http://kibana.logging:5601/dataset/; 129 | proxy_redirect off; 130 | } 131 | 132 | location /translations/ { 133 | proxy_pass http://kibana.logging:5601/translations/; 134 | proxy_redirect off; 135 | } 136 | 137 | location ^~ /built_assets/ { 138 | proxy_pass http://kibana.logging:5601/built_assets/; 139 | proxy_redirect off; 140 | } 141 | 142 | location /ui/ { 143 | proxy_pass http://kibana.logging:5601/ui/; 144 | proxy_redirect off; 145 | } 146 | 147 | location /spaces/ { 148 | proxy_pass http://kibana.logging:5601/spaces/; 149 | proxy_redirect off; 150 | } 151 | 152 | location /node_modules/ { 153 | proxy_pass http://kibana.logging:5601/node_modules/; 154 | proxy_redirect off; 155 | } 156 | 157 | location /bootstrap.js { 158 | proxy_pass http://kibana.logging:5601/bootstrap.js; 159 | proxy_redirect off; 160 | } 161 | 162 | location /internal/ { 163 | proxy_pass http://kibana.logging:5601/internal/; 164 | proxy_redirect off; 165 | } 166 | 167 | # location /moloch/ { 168 | # proxy_pass http://arkime.suricata:8005/moloch/; 169 | # proxy_redirect off; 170 | # } 171 | 172 | location ~ "^/([\d]{5}/.*)" { 173 | proxy_pass http://kibana.logging:5601/$1; 174 | proxy_redirect off; 175 | } 176 | 177 | location / { 178 | proxy_pass http://scirius.suricata:80; 179 | proxy_read_timeout 600; 180 | proxy_set_header Host $http_host; 181 | proxy_set_header X-Forwarded-Proto https; 182 | proxy_redirect off; 183 | client_max_body_size 100M; 184 | } 185 | } 186 | -------------------------------------------------------------------------------- /kubernetes/nginx/nginx-deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | annotations: 5 | labels: 6 | app: nginx 7 | name: nginx 8 | namespace: suricata 9 | spec: 10 | replicas: 1 11 | selector: 12 | matchLabels: 13 | app: nginx 14 | template: 15 | metadata: 16 | labels: 17 | app: nginx 18 | spec: 19 | automountServiceAccountToken: false 20 | 21 | containers: 22 | - name: nginx 23 | image: cgr.dev/chainguard/nginx:1.23.3 24 | 25 | ports: 26 | - name: http 27 | containerPort: 8080 28 | - name: https 29 | containerPort: 8443 30 | 31 | resources: 32 | requests: 33 | memory: 100Mi 34 | cpu: 50m 35 | limits: 36 | cpu: 1 37 | memory: 500Mi 38 | 39 | livenessProbe: 40 | tcpSocket: 41 | port: http 42 | periodSeconds: 10 43 | timeoutSeconds: 5 44 | successThreshold: 1 45 | failureThreshold: 6 46 | readinessProbe: 47 | tcpSocket: 48 | port: http 49 | initialDelaySeconds: 5 50 | periodSeconds: 5 51 | timeoutSeconds: 3 52 | successThreshold: 1 53 | failureThreshold: 3 54 | 55 | securityContext: 56 | allowPrivilegeEscalation: false 57 | capabilities: 58 | drop: 59 | - ALL 60 | privileged: false 61 | runAsNonRoot: true 62 | seccompProfile: 63 | type: RuntimeDefault 64 | 65 | volumeMounts: 66 | - mountPath: /static 67 | name: scirius-static 68 | readOnly: true 69 | - mountPath: /etc/nginx/conf.d/default.conf 70 | name: nginx-default-conf 71 | readOnly: true 72 | subPath: default.conf 73 | - mountPath: /etc/nginx/conf.d/selks6.conf 74 | name: nginx-selks-conf 75 | readOnly: true 76 | subPath: selks6.conf 77 | - mountPath: /etc/nginx/nginx.conf 78 | name: nginx-server-conf 79 | readOnly: true 80 | subPath: nginx.conf 81 | - mountPath: /etc/nginx/ssl 82 | name: nginx-tls 83 | readOnly: true 84 | 85 | restartPolicy: Always 86 | volumes: 87 | - name: scirius-static 88 | persistentVolumeClaim: 89 | claimName: scirius-static 90 | readOnly: true 91 | - name: nginx-tls 92 | secret: 93 | secretName: nginx-tls 94 | defaultMode: 0440 95 | - name: nginx-default-conf 96 | configMap: 97 | name: nginx-configmap 98 | items: 99 | - key: default.conf 100 | path: default.conf 101 | mode: 0440 102 | - name: nginx-server-conf 103 | configMap: 104 | name: nginx-configmap 105 | items: 106 | - key: nginx.conf 107 | path: nginx.conf 108 | mode: 0440 109 | - name: nginx-selks-conf 110 | configMap: 111 | name: nginx-configmap 112 | items: 113 | - key: selks6.conf 114 | path: selks6.conf 115 | mode: 0440 116 | -------------------------------------------------------------------------------- /kubernetes/nginx/nginx-ingress.yaml: -------------------------------------------------------------------------------- 1 | #jinja2: trim_blocks: True, lstrip_blocks: True 2 | --- 3 | apiVersion: networking.k8s.io/v1 4 | kind: Ingress 5 | metadata: 6 | name: nginx-ingress 7 | namespace: suricata 8 | spec: 9 | ingressClassName: nginx 10 | rules: 11 | - host: HOSTNAME 12 | http: 13 | paths: 14 | - path: / 15 | pathType: ImplementationSpecific 16 | backend: 17 | service: 18 | name: nginx 19 | port: 20 | number: 80 21 | # tls: 22 | # - hosts: 23 | # - HOSTNAME 24 | # secretName: nginx-tls-key 25 | -------------------------------------------------------------------------------- /kubernetes/nginx/nginx-owasp-configmap.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: nginx-owasp-configmap 5 | namespace: suricata 6 | data: 7 | docker-entrypoint.sh: | 8 | #!/bin/sh -e 9 | 10 | export DNS_SERVER=${DNS_SERVER:-$(grep -i '^nameserver' /etc/resolv.conf|head -n1|cut -d ' ' -f2)} 11 | 12 | ENV_VARIABLES=$(awk 'BEGIN{for(v in ENVIRON) print "$"v}') 13 | 14 | # FILES="/etc/nginx/nginx.conf /etc/nginx/conf.d/default.conf /etc/nginx/conf.d/logging.conf /etc/nginx/includes/location_common.conf /etc/modsecurity.d/modsecurity-override.conf" 15 | FILES="/etc/nginx/conf.d/logging.conf /etc/nginx/includes/location_common.conf /etc/modsecurity.d/modsecurity-override.conf" 16 | 17 | for FILE in $FILES; do 18 | if [ -f "$FILE" ]; then 19 | envsubst "$ENV_VARIABLES" <"$FILE" | sponge "$FILE" 20 | fi 21 | done 22 | 23 | . /opt/modsecurity/activate-rules.sh 24 | 25 | exec "$@" 26 | 27 | request-900-exclusion-rules-before-crs.conf: | 28 | # The purpose of this file is to hold LOCAL exceptions for your site. The 29 | # types of rules that would go into this file are one where you want to 30 | # short-circuit inspection and allow certain transactions to pass through 31 | # inspection or if you want to alter rules that are applied. 32 | 33 | # As a general rule: 34 | # ctl:ruleEngine -> place in REQUEST-900-EXCLUSION-RULES-BEFORE-CRS 35 | # ctl:ruleRemoveById -> place in REQUEST-900-EXCLUSION-RULES-BEFORE-CRS 36 | # ctl:ruleRemoveByMsg -> place in REQUEST-900-EXCLUSION-RULES-BEFORE-CRS 37 | # ctl:ruleRemoveByTag -> place in REQUEST-900-EXCLUSION-RULES-BEFORE-CRS 38 | # ctl:ruleRemoveTargetById -> place in REQUEST-900-EXCLUSION-RULES-BEFORE-CRS 39 | # ctl:ruleRemoveTargetByMsg -> place in REQUEST-900-EXCLUSION-RULES-BEFORE-CRS 40 | # ctl:ruleRemoveTargetByTag -> place in REQUEST-900-EXCLUSION-RULES-BEFORE-CRS 41 | # 42 | # SecRuleRemoveById -> place in RESPONSE-999-EXCLUSION-RULES-AFTER-CRS 43 | # SecRuleRemoveByMsg -> place in RESPONSE-999-EXCLUSION-RULES-AFTER-CRS 44 | # SecRuleRemoveByTag -> place in RESPONSE-999-EXCLUSION-RULES-AFTER-CRS 45 | # SecRuleUpdateActionById -> place in RESPONSE-999-EXCLUSION-RULES-AFTER-CRS 46 | # SecRuleUpdateTargetById -> place in RESPONSE-999-EXCLUSION-RULES-AFTER-CRS 47 | # SecRuleUpdateTargetByMsg -> place in RESPONSE-999-EXCLUSION-RULES-AFTER-CRS 48 | # SecRuleUpdateTargetByTag -> place in RESPONSE-999-EXCLUSION-RULES-AFTER-CRS 49 | 50 | SecRule REMOTE_ADDR "@ipMatch 10.42.0.0/16" \ 51 | "id:'1000',\ 52 | phase:1,\ 53 | pass,\ 54 | nolog,\ 55 | ctl:ruleEngine=off" 56 | 57 | response-999-exclusion-rules-after-crs.conf: | 58 | # The purpose of this file is to hold LOCAL exceptions for your site. The 59 | # types of rules that would go into this file are one where you want 60 | # to unconditionally disable rules or modify their actions during startup. 61 | 62 | nginx.conf: | 63 | load_module modules/ngx_http_modsecurity_module.so; 64 | 65 | user nginx; 66 | worker_processes 1; 67 | # pid /tmp/nginx.pid; 68 | pid /var/run/nginx.pid; 69 | include /etc/nginx/modules-enabled/*.conf; 70 | 71 | events { 72 | worker_connections 1024; 73 | } 74 | 75 | http { 76 | 77 | ## 78 | # Basic Settings 79 | ## 80 | 81 | sendfile on; 82 | tcp_nopush on; 83 | tcp_nodelay on; 84 | keepalive_timeout 65; 85 | types_hash_max_size 2048; 86 | client_max_body_size 20M; 87 | # server_tokens off; 88 | 89 | # server_names_hash_bucket_size 64; 90 | # server_name_in_redirect off; 91 | 92 | include /etc/nginx/mime.types; 93 | default_type application/octet-stream; 94 | 95 | ## 96 | # SSL Settings 97 | ## 98 | 99 | ssl_protocols TLSv1.2 TLSv1.3; 100 | ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384; 101 | ssl_stapling off; 102 | ssl_stapling_verify off; 103 | ssl_verify_client off; 104 | 105 | ## 106 | # Gzip Settings 107 | ## 108 | 109 | gzip on; 110 | 111 | # gzip_vary on; 112 | # gzip_proxied any; 113 | # gzip_comp_level 6; 114 | # gzip_buffers 16 8k; 115 | # gzip_http_version 1.1; 116 | # gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript; 117 | 118 | ## 119 | # Setup rootless 120 | ## 121 | 122 | # client_body_temp_path /tmp/client_temp; 123 | # proxy_temp_path /tmp/proxy_temp_path; 124 | # fastcgi_temp_path /tmp/fastcgi_temp; 125 | # uwsgi_temp_path /tmp/uwsgi_temp; 126 | # scgi_temp_path /tmp/scgi_temp; 127 | 128 | ## 129 | # Virtual Host Configs 130 | ## 131 | 132 | include /etc/nginx/conf.d/*.conf; 133 | } 134 | 135 | default.conf: | 136 | map $http_upgrade $connection_upgrade { 137 | default upgrade; 138 | '' close; 139 | } 140 | 141 | selks6.conf: | 142 | server { 143 | 144 | listen 8080; 145 | listen 8443 ssl; 146 | ssl_certificate /etc/nginx/ssl/tls.crt; 147 | ssl_certificate_key /etc/nginx/ssl/tls.key; 148 | 149 | server_name SELKS; 150 | 151 | access_log /var/log/nginx/scirius.access.log; 152 | error_log /var/log/nginx/scirius.error.log; 153 | 154 | include /etc/nginx/includes/location_common.conf; 155 | 156 | # https://docs.djangoproject.com/en/dev/howto/static-files/#serving-static-files-in-production 157 | location /static/ { # STATIC_URL 158 | alias /static/; # STATIC_ROOT 159 | expires 30d; 160 | } 161 | 162 | location /media/ { # MEDIA_URL 163 | alias /static/; # MEDIA_ROOT 164 | expires 30d; 165 | } 166 | 167 | location /plugins/ { 168 | proxy_pass http://kibana.logging:5601/plugins/; 169 | proxy_redirect off; 170 | } 171 | 172 | location /dlls/ { 173 | proxy_pass http://kibana.logging:5601/dlls/; 174 | proxy_redirect off; 175 | } 176 | 177 | location /socket.io/ { 178 | proxy_pass http://kibana.logging:5601/socket.io/; 179 | proxy_redirect off; 180 | } 181 | 182 | location /dataset/ { 183 | proxy_pass http://kibana.logging:5601/dataset/; 184 | proxy_redirect off; 185 | } 186 | 187 | location /translations/ { 188 | proxy_pass http://kibana.logging:5601/translations/; 189 | proxy_redirect off; 190 | } 191 | 192 | location ^~ /built_assets/ { 193 | proxy_pass http://kibana.logging:5601/built_assets/; 194 | proxy_redirect off; 195 | } 196 | 197 | location /ui/ { 198 | proxy_pass http://kibana.logging:5601/ui/; 199 | proxy_redirect off; 200 | } 201 | 202 | location /spaces/ { 203 | proxy_pass http://kibana.logging:5601/spaces/; 204 | proxy_redirect off; 205 | } 206 | 207 | location /node_modules/ { 208 | proxy_pass http://kibana.logging:5601/node_modules/; 209 | proxy_redirect off; 210 | } 211 | 212 | location /bootstrap.js { 213 | proxy_pass http://kibana.logging:5601/bootstrap.js; 214 | proxy_redirect off; 215 | } 216 | 217 | location /internal/ { 218 | proxy_pass http://kibana.logging:5601/internal/; 219 | proxy_redirect off; 220 | } 221 | 222 | # location /moloch/ { 223 | # proxy_pass http://arkime.suricata:8005/moloch/; 224 | # proxy_redirect off; 225 | # } 226 | 227 | location ~ "^/([\d]{5}/.*)" { 228 | proxy_pass http://kibana.logging:5601/$1; 229 | proxy_redirect off; 230 | } 231 | 232 | location / { 233 | proxy_pass http://scirius.suricata:80; 234 | proxy_read_timeout 600; 235 | proxy_set_header Host $http_host; 236 | proxy_set_header X-Forwarded-Proto https; 237 | proxy_redirect off; 238 | client_max_body_size 100M; 239 | } 240 | } 241 | -------------------------------------------------------------------------------- /kubernetes/nginx/nginx-owasp-deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | annotations: 5 | labels: 6 | app: nginx-owasp 7 | name: nginx-owasp 8 | namespace: suricata 9 | spec: 10 | replicas: 1 11 | selector: 12 | matchLabels: 13 | app: nginx-owasp 14 | template: 15 | metadata: 16 | annotations: 17 | labels: 18 | app: nginx-owasp 19 | spec: 20 | automountServiceAccountToken: false 21 | 22 | containers: 23 | - name: nginx 24 | image: owasp/modsecurity-crs:3.3.2-nginx-alpine 25 | 26 | ports: 27 | - name: http 28 | containerPort: 8080 29 | - name: https 30 | containerPort: 8443 31 | 32 | resources: 33 | requests: 34 | memory: 100Mi 35 | cpu: 50m 36 | limits: 37 | cpu: 1 38 | memory: 500Mi 39 | 40 | livenessProbe: 41 | httpGet: 42 | path: /healthz 43 | port: http 44 | readinessProbe: 45 | httpGet: 46 | path: /healthz 47 | port: http 48 | 49 | securityContext: 50 | allowPrivilegeEscalation: false 51 | privileged: false 52 | capabilities: 53 | drop: 54 | - ALL 55 | seccompProfile: 56 | type: RuntimeDefault 57 | 58 | volumeMounts: 59 | - mountPath: /static 60 | name: scirius-static 61 | readOnly: true 62 | - mountPath: /etc/nginx/conf.d/default.conf 63 | name: nginx-default-conf 64 | readOnly: true 65 | subPath: default.conf 66 | - mountPath: /etc/nginx/conf.d/selks6.conf 67 | name: nginx-selks-conf 68 | readOnly: true 69 | subPath: selks6.conf 70 | - mountPath: /etc/nginx/nginx.conf 71 | name: nginx-server-conf 72 | readOnly: true 73 | subPath: nginx.conf 74 | - mountPath: /etc/nginx/ssl 75 | name: nginx-tls 76 | readOnly: true 77 | 78 | - mountPath: /etc/modsecurity.d/owasp-crs/rules/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf 79 | name: nginx-modsecurity-request-900 80 | readOnly: true 81 | subPath: EXCLUSION 82 | - mountPath: /etc/modsecurity.d/owasp-crs/rules/RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf 83 | name: nginx-modsecurity-response-999 84 | readOnly: true 85 | subPath: EXCLUSION 86 | 87 | - mountPath: /docker-entrypoint.sh 88 | name: nginx-docker-entrypoint 89 | subPath: docker-entrypoint.sh 90 | 91 | restartPolicy: Always 92 | volumes: 93 | - name: scirius-static 94 | persistentVolumeClaim: 95 | claimName: scirius-static 96 | readOnly: true 97 | 98 | - name: nginx-default-conf 99 | configMap: 100 | name: nginx-owasp-configmap 101 | items: 102 | - key: default.conf 103 | path: default.conf 104 | mode: 0444 105 | - name: nginx-selks-conf 106 | configMap: 107 | name: nginx-owasp-configmap 108 | items: 109 | - key: selks6.conf 110 | path: selks6.conf 111 | mode: 0444 112 | - name: nginx-server-conf 113 | configMap: 114 | name: nginx-owasp-configmap 115 | items: 116 | - key: nginx.conf 117 | path: nginx.conf 118 | mode: 0444 119 | - name: nginx-tls 120 | secret: 121 | secretName: nginx-tls 122 | defaultMode: 0444 123 | 124 | - name: nginx-modsecurity-request-900 125 | configMap: 126 | name: nginx-owasp-configmap 127 | items: 128 | - key: request-900-exclusion-rules-before-crs.conf 129 | path: EXCLUSION 130 | mode: 0444 131 | - name: nginx-modsecurity-response-999 132 | configMap: 133 | name: nginx-owasp-configmap 134 | items: 135 | - key: response-999-exclusion-rules-after-crs.conf 136 | path: EXCLUSION 137 | mode: 0444 138 | 139 | - name: nginx-docker-entrypoint 140 | configMap: 141 | name: nginx-owasp-configmap 142 | items: 143 | - key: docker-entrypoint.sh 144 | path: docker-entrypoint.sh 145 | mode: 0555 146 | -------------------------------------------------------------------------------- /kubernetes/nginx/nginx-owasp-service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | annotations: 5 | labels: 6 | app: nginx-owasp 7 | name: nginx-owasp 8 | namespace: suricata 9 | spec: 10 | ports: 11 | - name: "https" 12 | port: 443 13 | targetPort: 8443 14 | - name: "http" 15 | port: 80 16 | targetPort: 8080 17 | selector: 18 | app: nginx-owasp 19 | sessionAffinity: None 20 | type: NodePort 21 | -------------------------------------------------------------------------------- /kubernetes/nginx/nginx-service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | annotations: 5 | labels: 6 | app: nginx 7 | name: nginx 8 | namespace: suricata 9 | spec: 10 | ports: 11 | - name: "https" 12 | port: 443 13 | targetPort: 8443 14 | - name: "http" 15 | port: 80 16 | targetPort: 8080 17 | selector: 18 | app: nginx 19 | sessionAffinity: None 20 | type: NodePort 21 | -------------------------------------------------------------------------------- /kubernetes/scirius/scirius-cronjob.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: ServiceAccount 4 | metadata: 5 | name: scirius-rules-refresh 6 | namespace: suricata 7 | labels: 8 | k8s-app: scirius-rules-refresh 9 | 10 | --- 11 | 12 | apiVersion: rbac.authorization.k8s.io/v1 13 | kind: Role 14 | metadata: 15 | name: scirius-rules-refresh 16 | namespace: suricata 17 | labels: 18 | k8s-app: scirius-rules-refresh 19 | rules: 20 | - apiGroups: 21 | - "" 22 | resources: 23 | - pods 24 | - pods/exec 25 | verbs: 26 | - '*' 27 | 28 | --- 29 | 30 | apiVersion: rbac.authorization.k8s.io/v1 31 | kind: RoleBinding 32 | metadata: 33 | name: scirius-rules-refresh 34 | namespace: suricata 35 | roleRef: 36 | kind: Role 37 | name: scirius-rules-refresh 38 | apiGroup: "" 39 | subjects: 40 | - kind: ServiceAccount 41 | name: scirius-rules-refresh 42 | namespace: suricata 43 | 44 | --- 45 | 46 | apiVersion: batch/v1 47 | kind: CronJob 48 | metadata: 49 | name: scirius-rules-refresh 50 | namespace: suricata 51 | labels: 52 | k8s-app: scirius-rules-refresh 53 | spec: 54 | # Run every day at 13:13 55 | schedule: "13 13 * * *" 56 | concurrencyPolicy: Forbid 57 | failedJobsHistoryLimit: 1 58 | successfulJobsHistoryLimit: 1 59 | jobTemplate: 60 | spec: 61 | template: 62 | spec: 63 | serviceAccountName: scirius-rules-refresh 64 | containers: 65 | - name: scirius-rules-refresh 66 | image: "bitnami/kubectl:latest" 67 | imagePullPolicy: Always 68 | command: ["bash","-c"] 69 | args: 70 | - | 71 | echo "Updating Suricata rules from Scirius" 72 | kubectl exec -n suricata $(kubectl get pod -n suricata -l app=scirius -o custom-columns=Name:.metadata.name --no-headers) -- python /opt/scirius/manage.py updatesuricata && echo "done." || (echo "ERROR" && exit 1) 73 | 74 | resources: 75 | requests: 76 | memory: 10Mi 77 | cpu: 5m 78 | 79 | securityContext: 80 | allowPrivilegeEscalation: false 81 | capabilities: 82 | drop: 83 | - ALL 84 | privileged: false 85 | readOnlyRootFilesystem: true 86 | runAsGroup: 1001 87 | runAsNonRoot: true 88 | runAsUser: 1001 89 | seccompProfile: 90 | type: RuntimeDefault 91 | 92 | securityContext: 93 | fsGroup: 1001 94 | 95 | restartPolicy: Never 96 | -------------------------------------------------------------------------------- /kubernetes/scirius/scirius-deployment.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | apiVersion: apps/v1 4 | kind: Deployment 5 | metadata: 6 | annotations: 7 | labels: 8 | app: scirius 9 | name: scirius 10 | namespace: suricata 11 | spec: 12 | replicas: 1 13 | selector: 14 | matchLabels: 15 | app: scirius 16 | template: 17 | metadata: 18 | annotations: 19 | labels: 20 | app: scirius 21 | spec: 22 | automountServiceAccountToken: false 23 | 24 | securityContext: 25 | fsGroup: 995 26 | seccompProfile: 27 | type: RuntimeDefault 28 | 29 | containers: 30 | - name: scirius 31 | image: ghcr.io/stamusnetworks/scirius:master 32 | env: 33 | - name: ALLOWED_HOSTS 34 | value: '*' 35 | - name: DEBUG 36 | value: "False" 37 | - name: ELASTICSEARCH_ADDRESS 38 | value: elasticsearch.logging:9200 39 | - name: EVEBOX_ADDRESS 40 | value: evebox.logging:5636 41 | - name: KIBANA7_DASHBOARDS_PATH 42 | value: /opt/selks/kibana7-dashboards 43 | - name: KIBANA_PROXY 44 | value: "True" 45 | - name: KIBANA_URL 46 | value: http://kibana.logging:5601 47 | - name: SCIRIUS_IN_SELKS 48 | value: "True" 49 | - name: SECRET_KEY 50 | valueFrom: 51 | secretKeyRef: 52 | name: scirius-secret 53 | key: password 54 | - name: SURICATA_UNIX_SOCKET 55 | value: /var/run/suricata/suricata-command.socket 56 | - name: USE_ELASTICSEARCH 57 | value: "True" 58 | - name: USE_EVEBOX 59 | value: "True" 60 | - name: USE_KIBANA 61 | value: "True" 62 | - name: USE_MOLOCH 63 | value: "True" 64 | - name: MOLOCH_URL 65 | value: http://arkime:8005 66 | - name: USE_SURICATA_STATS 67 | value: "True" 68 | 69 | ports: 70 | - name: http 71 | containerPort: 8000 72 | 73 | resources: 74 | requests: 75 | memory: 600Mi 76 | cpu: 100m 77 | limits: 78 | cpu: 500m 79 | memory: 1Gi 80 | 81 | securityContext: 82 | allowPrivilegeEscalation: false 83 | capabilities: 84 | drop: 85 | - ALL 86 | privileged: false 87 | runAsGroup: 995 88 | seccompProfile: 89 | type: RuntimeDefault 90 | 91 | livenessProbe: 92 | failureThreshold: 5 93 | periodSeconds: 30 94 | httpGet: 95 | path: / 96 | port: http 97 | readinessProbe: 98 | failureThreshold: 5 99 | periodSeconds: 30 100 | httpGet: 101 | path: / 102 | port: http 103 | startupProbe: 104 | initialDelaySeconds: 60 105 | failureThreshold: 18 106 | periodSeconds: 10 107 | httpGet: 108 | path: / 109 | port: http 110 | 111 | volumeMounts: 112 | - mountPath: /static/ 113 | name: scirius-static 114 | - mountPath: /data/ 115 | name: scirius-data 116 | - mountPath: /logs/ 117 | name: scirius-logs 118 | - mountPath: /rules 119 | name: suricata-rules 120 | - mountPath: /var/run/suricata 121 | name: suricata-run 122 | 123 | restartPolicy: Always 124 | volumes: 125 | - name: scirius-static 126 | persistentVolumeClaim: 127 | claimName: scirius-static 128 | - name: scirius-data 129 | persistentVolumeClaim: 130 | claimName: scirius-data 131 | - name: scirius-logs 132 | persistentVolumeClaim: 133 | claimName: scirius-logs 134 | 135 | - name: suricata-rules 136 | persistentVolumeClaim: 137 | claimName: suricata-rules 138 | - name: suricata-run 139 | persistentVolumeClaim: 140 | claimName: suricata-run 141 | -------------------------------------------------------------------------------- /kubernetes/scirius/scirius-pv.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | apiVersion: v1 4 | kind: PersistentVolume 5 | metadata: 6 | name: scirius-logs 7 | spec: 8 | capacity: 9 | storage: 1Gi 10 | volumeMode: Filesystem 11 | accessModes: 12 | - ReadWriteOnce 13 | persistentVolumeReclaimPolicy: Retain 14 | claimRef: 15 | name: scirius-logs 16 | namespace: suricata 17 | local: 18 | path: /data/scirius/logs/ 19 | nodeAffinity: 20 | required: 21 | nodeSelectorTerms: 22 | - matchExpressions: 23 | - key: kubernetes.io/hostname 24 | operator: In 25 | values: 26 | - HOSTNAME 27 | 28 | --- 29 | 30 | apiVersion: v1 31 | kind: PersistentVolume 32 | metadata: 33 | name: scirius-data 34 | spec: 35 | capacity: 36 | storage: 10Gi 37 | volumeMode: Filesystem 38 | accessModes: 39 | - ReadWriteOnce 40 | persistentVolumeReclaimPolicy: Retain 41 | claimRef: 42 | name: scirius-data 43 | namespace: suricata 44 | local: 45 | path: /data/scirius/data/ 46 | nodeAffinity: 47 | required: 48 | nodeSelectorTerms: 49 | - matchExpressions: 50 | - key: kubernetes.io/hostname 51 | operator: In 52 | values: 53 | - HOSTNAME 54 | 55 | --- 56 | 57 | apiVersion: v1 58 | kind: PersistentVolume 59 | metadata: 60 | name: scirius-static 61 | spec: 62 | capacity: 63 | storage: 1Gi 64 | volumeMode: Filesystem 65 | accessModes: 66 | - ReadWriteOnce 67 | persistentVolumeReclaimPolicy: Retain 68 | claimRef: 69 | name: scirius-static 70 | namespace: suricata 71 | local: 72 | path: /data/scirius/static/ 73 | nodeAffinity: 74 | required: 75 | nodeSelectorTerms: 76 | - matchExpressions: 77 | - key: kubernetes.io/hostname 78 | operator: In 79 | values: 80 | - HOSTNAME 81 | -------------------------------------------------------------------------------- /kubernetes/scirius/scirius-pvc.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: PersistentVolumeClaim 3 | metadata: 4 | labels: 5 | app: scirius-data 6 | name: scirius-data 7 | namespace: suricata 8 | spec: 9 | storageClassName: "local-storage" 10 | volumeName: scirius-data 11 | accessModes: 12 | - ReadWriteOnce 13 | resources: 14 | requests: 15 | storage: 100Mi 16 | 17 | --- 18 | 19 | apiVersion: v1 20 | kind: PersistentVolumeClaim 21 | metadata: 22 | labels: 23 | app: scirius-logs 24 | name: scirius-logs 25 | namespace: suricata 26 | spec: 27 | storageClassName: "local-storage" 28 | volumeName: scirius-logs 29 | accessModes: 30 | - ReadWriteOnce 31 | resources: 32 | requests: 33 | storage: 1Gi 34 | 35 | --- 36 | 37 | apiVersion: v1 38 | kind: PersistentVolumeClaim 39 | metadata: 40 | labels: 41 | app: scirius-static 42 | name: scirius-static 43 | namespace: suricata 44 | spec: 45 | storageClassName: "local-storage" 46 | volumeName: scirius-static 47 | accessModes: 48 | - ReadWriteMany 49 | resources: 50 | requests: 51 | storage: 100Mi 52 | -------------------------------------------------------------------------------- /kubernetes/scirius/scirius-secret.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Secret 3 | metadata: 4 | name: scirius-secret 5 | namespace: suricata 6 | type: kubernetes.io/basic-auth 7 | stringData: 8 | username: YWRtaW4= 9 | password: YWRtaW4= 10 | -------------------------------------------------------------------------------- /kubernetes/scirius/scirius-service.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | apiVersion: v1 4 | kind: Service 5 | metadata: 6 | name: scirius 7 | namespace: suricata 8 | labels: 9 | app: scirius 10 | spec: 11 | type: ClusterIP 12 | ports: 13 | - port: 80 14 | protocol: TCP 15 | name: http 16 | targetPort: 8000 17 | selector: 18 | app: scirius 19 | -------------------------------------------------------------------------------- /kubernetes/suricata/suricata-cronjob.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: ServiceAccount 4 | metadata: 5 | name: suricata-logrotate 6 | namespace: suricata 7 | labels: 8 | k8s-app: suricata-logrotate 9 | 10 | --- 11 | 12 | apiVersion: rbac.authorization.k8s.io/v1 13 | kind: Role 14 | metadata: 15 | name: suricata-logrotate 16 | namespace: suricata 17 | labels: 18 | k8s-app: suricata-logrotate 19 | rules: 20 | - apiGroups: 21 | - "" 22 | resources: 23 | - pods 24 | - pods/exec 25 | verbs: 26 | - '*' 27 | 28 | --- 29 | 30 | apiVersion: rbac.authorization.k8s.io/v1 31 | kind: RoleBinding 32 | metadata: 33 | name: suricata-logrotate 34 | namespace: suricata 35 | roleRef: 36 | kind: Role 37 | name: suricata-logrotate 38 | apiGroup: "" 39 | subjects: 40 | - kind: ServiceAccount 41 | name: suricata-logrotate 42 | namespace: suricata 43 | 44 | --- 45 | 46 | apiVersion: batch/v1 47 | kind: CronJob 48 | metadata: 49 | name: suricata-logrotate 50 | namespace: suricata 51 | labels: 52 | k8s-app: suricata-logrotate 53 | spec: 54 | # Run every day at 13:14 55 | schedule: "14 13 * * *" 56 | concurrencyPolicy: Forbid 57 | failedJobsHistoryLimit: 1 58 | successfulJobsHistoryLimit: 1 59 | jobTemplate: 60 | spec: 61 | template: 62 | spec: 63 | serviceAccountName: suricata-logrotate 64 | containers: 65 | - name: suricata-logrotate 66 | image: "bitnami/kubectl:latest" 67 | imagePullPolicy: Always 68 | command: ["bash","-c"] 69 | args: 70 | - | 71 | echo "Rotating Suricata logs" 72 | kubectl exec -n suricata $(kubectl get pod -n suricata -l service=suricata -o custom-columns=Name:.metadata.name --no-headers) -- logrotate -v /etc/logrotate.d/suricata $@ && echo "done." || (echo "ERROR" && exit 1) 73 | 74 | resources: 75 | requests: 76 | memory: 10Mi 77 | cpu: 5m 78 | 79 | securityContext: 80 | allowPrivilegeEscalation: false 81 | capabilities: 82 | drop: 83 | - ALL 84 | privileged: false 85 | readOnlyRootFilesystem: true 86 | runAsGroup: 1001 87 | runAsNonRoot: true 88 | runAsUser: 1001 89 | seccompProfile: 90 | type: RuntimeDefault 91 | securityContext: 92 | fsGroup: 1001 93 | 94 | restartPolicy: Never 95 | -------------------------------------------------------------------------------- /kubernetes/suricata/suricata-daemonset.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | apiVersion: apps/v1 4 | kind: DaemonSet 5 | metadata: 6 | annotations: 7 | labels: 8 | service: suricata 9 | name: suricata 10 | namespace: suricata 11 | spec: 12 | selector: 13 | matchLabels: 14 | service: suricata 15 | template: 16 | metadata: 17 | annotations: 18 | labels: 19 | service: suricata 20 | spec: 21 | automountServiceAccountToken: false 22 | 23 | hostNetwork: true 24 | 25 | initContainers: 26 | - name: cleanlog 27 | image: busybox:1.36.0 28 | imagePullPolicy: "IfNotPresent" 29 | command: ["sh", "-c"] 30 | args: 31 | - | 32 | > /var/log/suricata/suricata.log 33 | 34 | securityContext: 35 | allowPrivilegeEscalation: false 36 | capabilities: 37 | drop: 38 | - ALL 39 | privileged: false 40 | readOnlyRootFilesystem: true 41 | runAsGroup: 995 42 | runAsNonRoot: true 43 | runAsUser: 998 44 | seccompProfile: 45 | type: RuntimeDefault 46 | 47 | volumeMounts: 48 | - mountPath: /var/log/suricata 49 | name: suricata-log 50 | 51 | containers: 52 | - name: suricata 53 | image: jasonish/suricata:6.0.4-amd64 54 | env: 55 | - name: NODE_NAME 56 | valueFrom: 57 | fieldRef: 58 | fieldPath: spec.nodeName 59 | - name: CPU_LIMIT 60 | valueFrom: 61 | resourceFieldRef: 62 | containerName: suricata 63 | resource: limits.cpu 64 | - name: SURICATA_OPTIONS 65 | value: "-i eth0 -vvv --set sensor-name=suricata --set af-packet.1.threads=$(CPU_LIMIT) --set outputs.7.pcap-log.filename=log.$(NODE_NAME).%n.%t.pcap --set outputs.1.eve-log.filename=$(NODE_NAME)-eve.json" 66 | command: ["/etc/suricata/new_entrypoint.sh"] 67 | 68 | livenessProbe: 69 | exec: 70 | command: 71 | # Check if file has changed in the last 30 seconds. 72 | - bash 73 | - -c 74 | - | 75 | set -e 76 | find /var/log/suricata/ -mmin 0.5 | grep ${NODE_NAME}-eve.json 77 | readinessProbe: 78 | exec: 79 | command: 80 | - bash 81 | - -c 82 | - | 83 | set -e 84 | grep "All AFP capture threads are running." /var/log/suricata/suricata.log 85 | startupProbe: 86 | exec: 87 | command: 88 | - bash 89 | - -c 90 | - | 91 | set -e 92 | grep "All AFP capture threads are running." /var/log/suricata/suricata.log 93 | failureThreshold: 30 94 | 95 | resources: 96 | requests: 97 | memory: 1Gi 98 | cpu: 200m 99 | limits: 100 | cpu: 2 101 | memory: 4Gi 102 | 103 | securityContext: 104 | allowPrivilegeEscalation: false 105 | capabilities: 106 | add: 107 | - CHOWN 108 | - DAC_OVERRIDE 109 | - FSETID 110 | - NET_ADMIN 111 | - NET_RAW 112 | - SETGID 113 | - SETPCAP 114 | - SETUID 115 | - SYS_NICE 116 | drop: 117 | - ALL 118 | privileged: false 119 | runAsGroup: 995 120 | runAsNonRoot: true 121 | runAsUser: 0 122 | seccompProfile: 123 | type: RuntimeDefault 124 | 125 | volumeMounts: 126 | - mountPath: /var/log/suricata 127 | name: suricata-log 128 | - mountPath: /var/run/suricata 129 | name: suricata-run 130 | - mountPath: /etc/suricata/rules 131 | name: suricata-rules 132 | - mountPath: /etc/suricata/selks6-addin.yaml 133 | name: suricata-etcselks6-addin 134 | subPath: selks6-addin.yaml 135 | - mountPath: /etc/suricata/new_entrypoint.sh 136 | name: suricata-new-entrypoint 137 | subPath: new_entrypoint.sh 138 | - mountPath: /docker-entrypoint.sh 139 | name: suricata-docker-entrypoint 140 | subPath: docker-entrypoint.sh 141 | - mountPath: /etc/logrotate.d 142 | name: suricata-logrotate 143 | 144 | securityContext: 145 | fsGroup: 995 146 | seccompProfile: 147 | type: RuntimeDefault 148 | 149 | volumes: 150 | - name: suricata-log 151 | persistentVolumeClaim: 152 | claimName: suricata-log 153 | - name: suricata-run 154 | persistentVolumeClaim: 155 | claimName: suricata-run 156 | - name: suricata-rules 157 | persistentVolumeClaim: 158 | claimName: suricata-rules 159 | 160 | - name: suricata-etcselks6-addin 161 | configMap: 162 | name: suricata-etc 163 | items: 164 | - key: selks6-addin.yaml 165 | path: selks6-addin.yaml 166 | mode: 0444 167 | - name: suricata-new-entrypoint 168 | configMap: 169 | name: suricata-etc 170 | items: 171 | - key: new_entrypoint.sh 172 | path: new_entrypoint.sh 173 | mode: 0555 174 | - name: suricata-docker-entrypoint 175 | configMap: 176 | name: suricata-etc 177 | items: 178 | - key: docker-entrypoint.sh 179 | path: docker-entrypoint.sh 180 | mode: 0555 181 | - name: suricata-logrotate 182 | configMap: 183 | name: suricata-etc 184 | items: 185 | - key: logrotate 186 | path: suricata 187 | mode: 0444 188 | -------------------------------------------------------------------------------- /kubernetes/suricata/suricata-pv.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | apiVersion: v1 4 | kind: PersistentVolume 5 | metadata: 6 | name: suricata-log 7 | spec: 8 | capacity: 9 | storage: 10Gi 10 | volumeMode: Filesystem 11 | accessModes: 12 | - ReadWriteOnce 13 | persistentVolumeReclaimPolicy: Retain 14 | claimRef: 15 | name: suricata-log 16 | namespace: suricata 17 | local: 18 | path: /data/suricata/logs/ 19 | nodeAffinity: 20 | required: 21 | nodeSelectorTerms: 22 | - matchExpressions: 23 | - key: kubernetes.io/hostname 24 | operator: In 25 | values: 26 | - HOSTNAME 27 | 28 | --- 29 | 30 | apiVersion: v1 31 | kind: PersistentVolume 32 | metadata: 33 | name: suricata-logrotate 34 | spec: 35 | capacity: 36 | storage: 100Mi 37 | volumeMode: Filesystem 38 | accessModes: 39 | - ReadWriteOnce 40 | persistentVolumeReclaimPolicy: Retain 41 | claimRef: 42 | name: suricata-logrotate 43 | namespace: suricata 44 | local: 45 | path: /data/suricata/logrotate/ 46 | nodeAffinity: 47 | required: 48 | nodeSelectorTerms: 49 | - matchExpressions: 50 | - key: kubernetes.io/hostname 51 | operator: In 52 | values: 53 | - HOSTNAME 54 | 55 | --- 56 | 57 | apiVersion: v1 58 | kind: PersistentVolume 59 | metadata: 60 | name: suricata-run 61 | spec: 62 | capacity: 63 | storage: 100Mi 64 | volumeMode: Filesystem 65 | accessModes: 66 | - ReadWriteMany 67 | persistentVolumeReclaimPolicy: Retain 68 | claimRef: 69 | name: suricata-run 70 | namespace: suricata 71 | local: 72 | path: /data/suricata/run/ 73 | nodeAffinity: 74 | required: 75 | nodeSelectorTerms: 76 | - matchExpressions: 77 | - key: kubernetes.io/hostname 78 | operator: In 79 | values: 80 | - HOSTNAME 81 | 82 | --- 83 | 84 | apiVersion: v1 85 | kind: PersistentVolume 86 | metadata: 87 | name: suricata-rules 88 | spec: 89 | capacity: 90 | storage: 1Gi 91 | volumeMode: Filesystem 92 | accessModes: 93 | - ReadWriteMany 94 | persistentVolumeReclaimPolicy: Retain 95 | claimRef: 96 | name: suricata-rules 97 | namespace: suricata 98 | local: 99 | path: /data/suricata/rules/ 100 | nodeAffinity: 101 | required: 102 | nodeSelectorTerms: 103 | - matchExpressions: 104 | - key: kubernetes.io/hostname 105 | operator: In 106 | values: 107 | - HOSTNAME 108 | -------------------------------------------------------------------------------- /kubernetes/suricata/suricata-pvc.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | apiVersion: storage.k8s.io/v1 4 | kind: StorageClass 5 | metadata: 6 | name: local-storage 7 | provisioner: kubernetes.io/no-provisioner 8 | volumeBindingMode: WaitForFirstConsumer 9 | 10 | --- 11 | 12 | apiVersion: v1 13 | kind: PersistentVolumeClaim 14 | metadata: 15 | labels: 16 | app: suricata-log 17 | name: suricata-log 18 | namespace: suricata 19 | spec: 20 | storageClassName: "local-storage" 21 | volumeName: suricata-log 22 | accessModes: 23 | - ReadWriteOnce 24 | resources: 25 | requests: 26 | storage: 10Gi 27 | 28 | --- 29 | 30 | apiVersion: v1 31 | kind: PersistentVolumeClaim 32 | metadata: 33 | labels: 34 | app: suricata-logrotate 35 | name: suricata-logrotate 36 | namespace: suricata 37 | spec: 38 | storageClassName: "local-storage" 39 | volumeName: suricata-logrotate 40 | accessModes: 41 | - ReadWriteOnce 42 | resources: 43 | requests: 44 | storage: 100Mi 45 | 46 | --- 47 | 48 | apiVersion: v1 49 | kind: PersistentVolumeClaim 50 | metadata: 51 | labels: 52 | app: suricata-run 53 | name: suricata-run 54 | namespace: suricata 55 | spec: 56 | storageClassName: "local-storage" 57 | volumeName: suricata-run 58 | accessModes: 59 | - ReadWriteOnce 60 | resources: 61 | requests: 62 | storage: 100Mi 63 | 64 | --- 65 | 66 | apiVersion: v1 67 | kind: PersistentVolumeClaim 68 | metadata: 69 | labels: 70 | app: suricata-rules 71 | name: suricata-rules 72 | namespace: suricata 73 | spec: 74 | storageClassName: "local-storage" 75 | volumeName: suricata-rules 76 | accessModes: 77 | - ReadWriteMany 78 | resources: 79 | requests: 80 | storage: 1Gi 81 | -------------------------------------------------------------------------------- /kubernetes/suricata/suricata-stdout.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | apiVersion: apps/v1 4 | kind: DaemonSet 5 | metadata: 6 | name: suricata 7 | namespace: suricata 8 | spec: 9 | selector: 10 | matchLabels: 11 | app: suricata 12 | template: 13 | metadata: 14 | labels: 15 | app: suricata 16 | name: suricata 17 | spec: 18 | hostNetwork: true 19 | 20 | containers: 21 | - name: suricata 22 | image: jasonish/suricata:master-amd64 23 | command: 24 | - /usr/bin/suricata 25 | - -i 26 | - enx24b6ff700899 27 | 28 | resources: 29 | requests: 30 | memory: 500Mi 31 | cpu: 150m 32 | limits: 33 | cpu: 2 34 | memory: 4000Mi 35 | 36 | securityContext: 37 | capabilities: 38 | add: [NET_ADMIN, SYS_NICE] 39 | 40 | volumeMounts: 41 | - mountPath: /host/dev 42 | name: dev 43 | - name: "varlog" 44 | mountPath: /var/log/suricata 45 | 46 | # suricata-tail-eve-log container 47 | - name: suricata-tail-eve-log 48 | image: bash 49 | command: 50 | - tail 51 | - -F 52 | - /var/log/suricata/eve.json 53 | 54 | resources: 55 | requests: 56 | memory: 0Mi 57 | 58 | volumeMounts: 59 | - name: "varlog" 60 | mountPath: /var/log/suricata 61 | 62 | # suricata-tail-fast-log container 63 | - name: suricata-tail-fast-log 64 | image: bash 65 | command: 66 | - tail 67 | - -F 68 | - /var/log/suricata/fast.log 69 | 70 | resources: 71 | requests: 72 | memory: 0Mi 73 | 74 | volumeMounts: 75 | - name: "varlog" 76 | mountPath: /var/log/suricata 77 | 78 | # suricata-tail-stats-log container 79 | - name: suricata-tail-stats-log 80 | image: bash 81 | command: 82 | - tail 83 | - -F 84 | - /var/log/suricata/stats.log 85 | 86 | resources: 87 | requests: 88 | memory: 0Mi 89 | 90 | volumeMounts: 91 | - name: "varlog" 92 | mountPath: /var/log/suricata 93 | 94 | # suricata-tail-suricata-log container 95 | - name: suricata-tail-suricata-log 96 | image: bash 97 | command: 98 | - tail 99 | - -F 100 | - /var/log/suricata/suricata.log 101 | 102 | resources: 103 | requests: 104 | memory: 0Mi 105 | 106 | volumeMounts: 107 | - name: "varlog" 108 | mountPath: /var/log/suricata 109 | 110 | volumes: 111 | - name: dev 112 | hostPath: 113 | path: /dev 114 | 115 | - name: "varlog" 116 | emptyDir: {} 117 | -------------------------------------------------------------------------------- /scripts/SELKS3-SELKS4/README.rst: -------------------------------------------------------------------------------- 1 | 2 | Testing upgrade scritps(s) for SELKS 3 to SELKS 4 upgrade. 3 | 4 | Please use only in test/qa setups. 5 | 6 | `How to <https://github.com/StamusNetworks/SELKS/wiki/SELKS-3.0-to-SELKS-4.0-upgrades/>`_. 7 | 8 | -------------------------------------------------------------------------------- /scripts/SELKS4-SELKS5/README.rst: -------------------------------------------------------------------------------- 1 | 2 | Testing upgrade scritps(s) for SELKS 4 to SELKS 5 upgrade. 3 | 4 | Please use only in test/qa setups. 5 | 6 | 7 | -------------------------------------------------------------------------------- /scripts/SELKS4-SELKS5/SN-S4-S5-ES-Reindex.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright(C) 2018, Stamus Networks 4 | # All rights reserved 5 | # Written by Laurent Defert <lds@stamus-networks.com> 6 | # 7 | # Please run on Debian 8 | # 9 | # This script comes with ABSOLUTELY NO WARRANTY! 10 | # 11 | 12 | 13 | set -x 14 | 15 | LOGFILE=/var/log/logstash-migration.log 16 | ERRFILE=/var/log/logstash-migration-error.log 17 | ELASTICSEARCH=http://localhost:9200 18 | IDXFILE=/.reindex 19 | TODAY="$(cat "$IDXFILE")" 20 | 21 | if [ "$TODAY" == "" ] 22 | then 23 | date "+%Y.%m.%d" > /.reindex 24 | TODAY="$(cat "$IDXFILE")" 25 | fi 26 | 27 | function curl_es() 28 | { 29 | curl --silent --show-error "$@" 2>&1 30 | return $? 31 | } 32 | 33 | function curl_simple() 34 | { 35 | res="$(curl_es "$@")" 36 | if [ $? != 0 ] 37 | then 38 | return 1 39 | fi 40 | if [ "$(jq .acknowledged <<< "$res")" != true ] 41 | then 42 | return 1 43 | fi 44 | } 45 | 46 | function reindex() 47 | { 48 | index="$1" 49 | echo -n "Reindexing $index... " >> $LOGFILE 50 | size="$(curl_es "$ELASTICSEARCH/$index/_stats/store" | jq ._all.total.store.size_in_bytes)" 51 | free="$(curl_es "$ELASTICSEARCH/_cluster/stats" | jq .nodes.fs.available_in_bytes)" 52 | 53 | if [ "$size" == "" ] || [ "$free" == "" ] 54 | then 55 | echo "Cannot parse disk space for index $index" >> $ERRFILE 56 | echo "failed" >> $LOGFILE 57 | return 1 58 | fi 59 | 60 | if [ "$size" -gt "$free" ] 61 | then 62 | echo "Not enough space available for index $index ($size > $free)" >> $ERRFILE 63 | echo "failed" >> $LOGFILE 64 | return 1 65 | fi 66 | 67 | res="$(curl_es -XPOST -H 'Content-Type: application/json' "$ELASTICSEARCH/_reindex" -d ' 68 | { 69 | "conflicts": "proceed", 70 | "source": { 71 | "index": "'"$index"'" 72 | }, 73 | "dest": { 74 | "index": "'"$index-1"'", 75 | "op_type": "create" 76 | } 77 | }')" 78 | status=$? 79 | 80 | failures="$(echo "$res" | jq -r '.failures | .[] | ([.index, .cause.type, ":", .cause.reason] | join(" "))')" 81 | 82 | if [ "$failures" != "" ] 83 | then 84 | echo "Failures occured while reindexing $index:" >> $ERRFILE 85 | echo "$failures" >> $ERRFILE 86 | status=1 87 | fi 88 | 89 | if [ "$status" == 0 ] 90 | then 91 | curl_simple -XDELETE "$ELASTICSEARCH/$index" 92 | echo "ok" >> $LOGFILE 93 | else 94 | echo "Reindexing $index failed" >> $ERRFILE 95 | echo "failed" >> $LOGFILE 96 | fi 97 | return $status 98 | } 99 | 100 | echo "Reindex start: $(date)" 101 | 102 | if [ "$1" == "today" ] 103 | then 104 | # Lookup today indices 105 | ret=0 106 | for index in $(curl $ELASTICSEARCH/_cat/indices | grep '^green \+open \+logstash-' | awk '{print $3}' | grep "$TODAY$") 107 | do 108 | reindex "$index" || ret=1 109 | done 110 | exit $ret 111 | else 112 | today_nbr="$(tr -d . <<< "$TODAY")" 113 | ret=0 114 | for index in $(curl $ELASTICSEARCH/_cat/indices | grep '^green \+open \+logstash-\([a-z]\+-\)\?[0-9]\{4\}\.[0-9]\{2\}\.[0-9]\{2\} ' | awk '{print $3}' | sort -r -s -t - -k3) 115 | do 116 | date="$(sed -e 's/^.*-//' <<< "$index" | tr -d .)" 117 | if [ "$date" -lt "$today_nbr" ] 118 | then 119 | reindex "$index" || ret=1 120 | fi 121 | done 122 | if [ "$ret" == 0 ] && [ "$1" == 0 ] 123 | then 124 | rm $IDXFILE 125 | fi 126 | echo Done >> $LOGFILE 127 | fi 128 | 129 | echo "Reindex end: $(date)" 130 | -------------------------------------------------------------------------------- /scripts/SELKS5-SELKS6/README.rst: -------------------------------------------------------------------------------- 1 | 2 | Testing upgrade scritps(s) for SELKS 5 to SELKS 6 upgrade. 3 | 4 | Please test first in test/qa setups. 5 | 6 | 7 | -------------------------------------------------------------------------------- /staging/config/hooks/live/all_chroot_update-initramfs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # This is a hook for live-helper(7) to rebuild the initramfs image. 4 | # To enable it, copy or symlink this hook into your config/chroot_local-hooks 5 | # directory. 6 | # 7 | # Note: You only want to use this hook if you have modified any initramfs-script 8 | # during the build and need to refresh the initrd.img for that purpose. 9 | 10 | for KERNEL in /boot/vmlinuz-* 11 | do 12 | VERSION="$(basename ${KERNEL} | sed -e 's|vmlinuz-||')" 13 | 14 | update-initramfs -k ${VERSION} -t -u 15 | done 16 | 17 | cat << EOF 18 | ******************** 19 | end of hook 20 | ******************** 21 | EOF 22 | -------------------------------------------------------------------------------- /staging/config/hooks/live/chroot-inside-Debian-Live.hook.chroot: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright Stamus Networks, 2018 4 | # All rights reserved 5 | # Debian Live/Install ISO script - oss@stamus-networks.com 6 | # 7 | # Please run on Debian Stretch 8 | 9 | set -ex 10 | 11 | # Setting up the LIVE root (during install on disk it is preseeded) 12 | echo "root:StamusNetworks" | chpasswd 13 | 14 | # Enable color output and the "ll" command in shell 15 | echo " export LS_OPTIONS='--color=auto'" >> /root/.bashrc 16 | echo " alias ll='ls $LS_OPTIONS -l'" >> /root/.bashrc 17 | 18 | 19 | # Set up the host name 20 | echo "SELKS" > /etc/hostname 21 | 22 | # Enable the ssh banners 23 | sed -i -e 's|\#Banner \/etc\/issue\.net|Banner \/etc\/issue\.net|' /etc/ssh/sshd_config 24 | 25 | # Edit the Icon "Install Debian Stretch" name on a Live Desktop 26 | # to "Install SELKS" 27 | sed -i -e 's|Name\=Install Debian sid|Name\=Install SELKS|' /usr/share/applications/debian-installer-launcher.desktop 28 | 29 | # First time setup 30 | 31 | cat >> /etc/skel/Desktop/FirstTimeSetup.txt <<EOF 32 | 33 | It is always recommended to follow the latest docs: 34 | https://github.com/StamusNetworks/SELKS/wiki 35 | 36 | Please go to the end of the brief below for production setup considerations. 37 | 38 | First time setup: 39 | 40 | Non interactive, airgapped mode. 41 | The below command will setup the selks installation: 42 | - in non-interactive mode 43 | - install all containers (elasticsearch/suricata/ngingx/logstash/kibana/scirius/evebox/portainer) without pulling anything from the internet 44 | - use the interface tppdummy0 as sniffing interface 45 | - use 8GB of RAM for Elasticsearch 46 | - start up the installation (docker compose) 47 | 48 | Examples: 49 | 50 | 51 | cd /opt/selksd/SELKS/docker/ && \ 52 | ./easy-setup.sh --non-interactive --no-pull-containers -i tppdummy0 \ 53 | --iA --restart-mode always --es-memory 8G && \ 54 | docker-compose up -d 55 | 56 | 57 | Interactive with latest updated containers and software: 58 | 59 | - update/pull and install all containers (elasticsearch/suricata/ngingx/logstash/kibana/scirius/evebox/portainer) 60 | - use the interface tppdummy0 as sniffing interface 61 | - use 8GB of RAM for Elasticsearch, 1GB 62 | - start up the installation (docker compose) 63 | 64 | Example: 65 | 66 | cd /opt/selksd/SELKS/docker/ 67 | docker-compose down 68 | git pull 69 | ./easy-setup.sh --iA --es-memory 8G 70 | docker-compose pull 71 | docker-compose up -d --force-recreate 72 | 73 | 74 | Setting up dummy interface 75 | If you would not want to sniff on specific system interface and want to set up a dummy interface for sniffing to replay for example specific pcap cases: 76 | 77 | Example: 78 | 79 | ip link add tppdummy0 type dummy && \ 80 | ip link set tppdummy0 up && \ 81 | ifconfig tppdummy0 mtu 1572 82 | 83 | Production setup considerations: 84 | https://github.com/StamusNetworks/SELKS/wiki/Docker#production-setup 85 | 86 | EOF 87 | 88 | # copy for root to 89 | cp /etc/skel/Desktop/FirstTimeSetup.txt /root/Desktop/ 90 | 91 | # Clean devel and some others packages 92 | apt-get -y remove bison autoconf automake libc6-dev autotools-dev libpcap-dev libnet1-dev libcap-ng-dev \ 93 | libnetfilter-queue-dev libnss3-dev libnspr4-dev \ 94 | xscreensaver xscreensaver-data manpages-dev libjansson-dev \ 95 | ghostscript x11proto-core-dev linux-libc-dev \ 96 | rpm alien sane-utils libsane rpm2cpio \ 97 | libx11-dev libx11-doc m4 98 | 99 | # Docker install 100 | apt install apt-transport-https ca-certificates curl gnupg lsb-release -y 101 | curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg 102 | 103 | echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/debian \ 104 | $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null 105 | 106 | apt update && apt-get install -y docker-ce docker-ce-cli containerd.io 107 | 108 | curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose 109 | chmod +x /usr/local/bin/docker-compose 110 | ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose 111 | 112 | /bin/systemctl enable docker && \ 113 | /bin/systemctl start docker 114 | /bin/systemctl daemon-reload 115 | 116 | ip link add tppdummy0 type dummy && \ 117 | ip link set tppdummy0 up && \ 118 | ifconfig tppdummy0 mtu 1572 119 | 120 | mkdir -p /opt/selksd/ 121 | 122 | cd /opt/selksd/ && \ 123 | git clone https://github.com/StamusNetworks/SELKS.git && cd SELKS/docker/ && \ 124 | uname -a && whoami && echo $UID 125 | 126 | mkdir -p /opt/selksd/SELKS/docker/tar_images 127 | 128 | apt update && apt-get install -y python3-requests 129 | 130 | mkdir -p /opt/selksd/pull/ 131 | cd /opt/selksd/pull/ && \ 132 | git clone https://github.com/NotGlop/docker-drag.git && \ 133 | python3 docker-drag/docker_pull.py jasonish/suricata:master-amd64 && \ 134 | python3 docker-drag/docker_pull.py python:3.9.5-slim-buster && \ 135 | python3 docker-drag/docker_pull.py hello-world:latest && \ 136 | python3 docker-drag/docker_pull.py portainer/portainer-ce:latest && \ 137 | python3 docker-drag/docker_pull.py nginx:latest && \ 138 | python3 docker-drag/docker_pull.py elastic/elasticsearch:7.16.1 && \ 139 | python3 docker-drag/docker_pull.py elastic/kibana:7.16.1 && \ 140 | python3 docker-drag/docker_pull.py elastic/logstash:7.16.1 && \ 141 | python3 docker-drag/docker_pull.py jasonish/suricata:master-amd64 && \ 142 | python3 docker-drag/docker_pull.py ghcr.io/stamusnetworks/scirius:master && \ 143 | python3 docker-drag/docker_pull.py jasonish/evebox:master && \ 144 | python3 docker-drag/docker_pull.py ghcr.io/stamusnetworks/arkimeviewer:master 145 | 146 | mv /opt/selksd/pull/*.tar /opt/selksd/SELKS/docker/tar_images 147 | rm -rf /opt/selksd/pull/ 148 | 149 | apt-get autoremove -y 150 | apt-get clean && \ 151 | cat /dev/null > ~/.bash_history && history -c 152 | 153 | -------------------------------------------------------------------------------- /staging/config/hooks/live/menues-changes-live-custom-kernel-choice.hook.binary: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # IF kustom kernel option is chosen: 4 | # remove the live menu since different kernel versions and custom flavours 5 | # can potentially fail to load in LIVE depending on the given environment. 6 | # so we create a file for execution at the binary stage to remove the 7 | # live menu choice. That leaves the options to install. 8 | 9 | sed -i -e 's|include live\.cfg| |' isolinux/menu.cfg 10 | 11 | -------------------------------------------------------------------------------- /staging/config/hooks/live/menues-changes.hook.binary: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # changes of the wording (adding Stamus) in the 4 | # menu names 5 | 6 | sed -i -e 's|menu label \^Live|menu label \^Stamus SELKS Live|' isolinux/live.cfg 7 | sed -i -e 's|menu label \^Install|menu label \^Stamus SELKS Install|' isolinux/install.cfg 8 | sed -i -e 's|menu label \^Graphical install|menu label \^Stamus SELKS Graphical install|' isolinux/install.cfg 9 | 10 | -------------------------------------------------------------------------------- /staging/etc/default/evebox: -------------------------------------------------------------------------------- 1 | # The URL to Elastic Search 2 | ELASTICSEARCH_URL="-e http://localhost:9200" 3 | 4 | # Config file. 5 | # CONFIG="-c /etc/evebox.yaml" 6 | 7 | # Other options. 8 | EVEBOX_OPTS="--host localhost" 9 | -------------------------------------------------------------------------------- /staging/etc/iceweasel/profile/bookmarks.html: -------------------------------------------------------------------------------- 1 | <!-- This Source Code Form is subject to the terms of the Mozilla Public 2 | - License, v. 2.0. If a copy of the MPL was not distributed with this 3 | - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> 4 | 5 | <!DOCTYPE NETSCAPE-Bookmark-file-1> 6 | <!-- This is an automatically generated file. 7 | It will be read and overwritten. 8 | DO NOT EDIT! --> 9 | <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8"> 10 | <TITLE>Bookmarks 11 |

Bookmarks

12 | 13 |

14 |

Bookmarks Toolbar Folder

15 |
Add bookmarks to this folder to see them displayed on the Bookmarks Toolbar 16 |

17 |

Getting Started 18 |

19 |

S E L K S - scirius and dashboards

20 |

21 |

Scirius ruleset management 22 |
IDS-ALL-Events 23 |

24 |

S E L K S Help and Info

25 |

26 |

Suricata IDPS 27 |
Suricata IDPS wiki 28 |
OISF 29 |
ELK - Elasticsearch,Logstash,Kibana 30 |
Scirius 31 |
Stamus Networks - I Do See 32 |
SELKS wiki 33 | 34 | 35 |

36 |

37 | -------------------------------------------------------------------------------- /staging/etc/issue.net: -------------------------------------------------------------------------------- 1 | _____ __ _ __ _____ ________ __ _______ 2 | / ___// /_____ _____ ___ __ _______/ | / / / ___// ____/ / / //_/ ___/ 3 | \__ \/ __/ __ `/ __ `__ \/ / / / ___/ |/ / \__ \/ __/ / / / ,< \__ \ 4 | ___/ / /_/ /_/ / / / / / / /_/ (__ ) /| / ___/ / /___/ /___/ /| |___/ / 5 | /____/\__/\__,_/_/ /_/ /_/\__,_/____/_/ |_/ /____/_____/_____/_/ |_/____/ 6 | 7 | 8 | !!! All connections are monitored and recorded !!! 9 | !!! Disconnect IMMEDIATELY if you are not an authorized user !!! 10 | 11 | -------------------------------------------------------------------------------- /staging/etc/logrotate.d/suricata: -------------------------------------------------------------------------------- 1 | /var/log/suricata/eve.json { 2 | daily 3 | rotate 30 4 | olddir /var/log/suricata/StatsByDate/ 5 | compress 6 | missingok 7 | notifempty 8 | dateext 9 | postrotate 10 | /bin/kill -HUP $(cat /var/run/suricata.pid) 11 | endscript 12 | } 13 | 14 | # to see status 15 | # cat /var/lib/logrotate/status 16 | # to manually test - 17 | # logrotate --force /etc/logrotate.d/suricata 18 | -------------------------------------------------------------------------------- /staging/etc/logstash/conf.d/logstash.conf: -------------------------------------------------------------------------------- 1 | input { 2 | file { 3 | path => ["/var/log/suricata/*.json"] 4 | #sincedb_path => ["/var/lib/logstash/"] 5 | sincedb_path => ["/var/cache/logstash/sincedbs/since.db"] 6 | codec => json 7 | type => "SELKS" 8 | } 9 | 10 | } 11 | 12 | filter { 13 | if [type] == "SELKS" { 14 | 15 | date { 16 | match => [ "timestamp", "ISO8601" ] 17 | } 18 | 19 | ruby { 20 | code => " 21 | if event.get('[event_type]') == 'fileinfo' 22 | event.set('[fileinfo][type]', event.get('[fileinfo][magic]').to_s.split(',')[0]) 23 | end 24 | " 25 | } 26 | ruby { 27 | code => " 28 | if event.get('[event_type]') == 'alert' 29 | sp = event.get('[alert][signature]').to_s.split(' group ') 30 | if (sp.length == 2) and /\A\d+\z/.match(sp[1]) 31 | event.set('[alert][signature]', sp[0]) 32 | end 33 | end 34 | " 35 | } 36 | 37 | metrics { 38 | meter => [ "eve_insert" ] 39 | add_tag => "metric" 40 | flush_interval => 30 41 | } 42 | } 43 | 44 | if [http] { 45 | useragent { 46 | source => "[http][http_user_agent]" 47 | target => "[http][user_agent]" 48 | } 49 | } 50 | if [src_ip] { 51 | geoip { 52 | source => "src_ip" 53 | target => "geoip" 54 | #database => "/opt/logstash/vendor/geoip/GeoLiteCity.dat" 55 | #add_field => [ "[geoip][coordinates]", "%{[geoip][longitude]}" ] 56 | #add_field => [ "[geoip][coordinates]", "%{[geoip][latitude]}" ] 57 | } 58 | } 59 | if [dest_ip] { 60 | geoip { 61 | source => "dest_ip" 62 | target => "geoip" 63 | #database => "/opt/logstash/vendor/geoip/GeoLiteCity.dat" 64 | #add_field => [ "[geoip][coordinates]", "%{[geoip][longitude]}" ] 65 | #add_field => [ "[geoip][coordinates]", "%{[geoip][latitude]}" ] 66 | } 67 | } 68 | } 69 | 70 | output { 71 | if [event_type] and [event_type] != 'stats' { 72 | elasticsearch { 73 | hosts => "127.0.0.1" 74 | index => "logstash-%{event_type}-%{+YYYY.MM.dd}" 75 | template_overwrite => true 76 | template => "/etc/logstash/elasticsearch7-template.json" 77 | } 78 | } else { 79 | elasticsearch { 80 | hosts => "127.0.0.1" 81 | index => "logstash-%{+YYYY.MM.dd}" 82 | template_overwrite => true 83 | template => "/etc/logstash/elasticsearch7-template.json" 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /staging/etc/logstash/elasticsearch5-template.json: -------------------------------------------------------------------------------- 1 | { 2 | "template" : "logstash-*", 3 | "version" : 50001, 4 | "settings" : { 5 | "number_of_replicas": 0, 6 | "index.refresh_interval" : "5s" 7 | }, 8 | "mappings" : { 9 | "_default_" : { 10 | "_all" : {"enabled" : true, "norms" : false}, 11 | "dynamic_templates" : [ { 12 | "message_field" : { 13 | "path_match" : "message", 14 | "match_mapping_type" : "string", 15 | "mapping" : { 16 | "type" : "text", 17 | "norms" : false 18 | } 19 | } 20 | }, { 21 | "string_fields" : { 22 | "match" : "*", 23 | "match_mapping_type" : "string", 24 | "mapping" : { 25 | "type" : "text", "norms" : false, 26 | "fields" : { 27 | "keyword" : { "type": "keyword", "index": "not_analyzed", "ignore_above": 256 }, 28 | "raw" : { "type": "keyword", "index": "not_analyzed", "ignore_above": 256 } 29 | } 30 | } 31 | } 32 | } ], 33 | "properties" : { 34 | "@timestamp": { "type": "date", "include_in_all": false }, 35 | "@version": { "type": "keyword", "include_in_all": false }, 36 | "geoip" : { 37 | "dynamic": true, 38 | "properties" : { 39 | "ip": { "type": "ip" }, 40 | "location" : { "type" : "geo_point" }, 41 | "latitude" : { "type" : "half_float" }, 42 | "longitude" : { "type" : "half_float" } 43 | } 44 | }, 45 | "dest_ip": { 46 | "type": "ip", 47 | "fields": { 48 | "raw": {"index": "not_analyzed", "type": "keyword"}, 49 | "keyword": {"index": "not_analyzed", "type": "keyword"} 50 | } 51 | }, 52 | "src_ip": { 53 | "type": "ip", 54 | "fields": { 55 | "raw": {"index": "not_analyzed", "type": "keyword"}, 56 | "keyword": {"index": "not_analyzed", "type": "keyword"} 57 | } 58 | } 59 | } 60 | } 61 | } 62 | } -------------------------------------------------------------------------------- /staging/etc/logstash/elasticsearch6-template.json: -------------------------------------------------------------------------------- 1 | { 2 | "template" : "logstash-*", 3 | "version" : 60001, 4 | "settings" : { 5 | "number_of_replicas": 0, 6 | "index.refresh_interval" : "5s" 7 | }, 8 | "mappings" : { 9 | "_default_" : { 10 | "dynamic_templates" : [ { 11 | "message_field" : { 12 | "path_match" : "message", 13 | "match_mapping_type" : "string", 14 | "mapping" : { 15 | "type" : "text", 16 | "norms" : false 17 | } 18 | } 19 | }, { 20 | "string_fields" : { 21 | "match" : "*", 22 | "match_mapping_type" : "string", 23 | "mapping" : { 24 | "type" : "text", "norms" : false, 25 | "fields" : { 26 | "keyword" : { "type": "keyword", "ignore_above": 256 } 27 | } 28 | } 29 | } 30 | } ], 31 | "properties" : { 32 | "@timestamp": { "type": "date"}, 33 | "@version": { "type": "keyword"}, 34 | "geoip" : { 35 | "dynamic": true, 36 | "properties" : { 37 | "ip": { "type": "ip" }, 38 | "location" : { "type" : "geo_point" }, 39 | "latitude" : { "type" : "half_float" }, 40 | "longitude" : { "type" : "half_float" } 41 | } 42 | } 43 | } 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /staging/etc/logstash/elasticsearch7-template.json: -------------------------------------------------------------------------------- 1 | { 2 | "template" : "logstash-*", 3 | "version" : 60001, 4 | "settings" : { 5 | "number_of_replicas": 0, 6 | "index.refresh_interval" : "5s" 7 | }, 8 | "mappings" : { 9 | "dynamic_templates" : [ { 10 | "message_field" : { 11 | "path_match" : "message", 12 | "match_mapping_type" : "string", 13 | "mapping" : { 14 | "type" : "text", 15 | "norms" : false 16 | } 17 | } 18 | }, { 19 | "string_fields" : { 20 | "match" : "*", 21 | "match_mapping_type" : "string", 22 | "mapping" : { 23 | "type" : "text", "norms" : false, 24 | "fields" : { 25 | "keyword" : { "type": "keyword", "ignore_above": 256 } 26 | } 27 | } 28 | } 29 | } ], 30 | "properties" : { 31 | "@timestamp": { "type": "date"}, 32 | "@version": { "type": "keyword"}, 33 | "geoip" : { 34 | "dynamic": true, 35 | "properties" : { 36 | "ip": { "type": "ip" }, 37 | "location" : { "type" : "geo_point" }, 38 | "latitude" : { "type" : "half_float" }, 39 | "longitude" : { "type" : "half_float" } 40 | } 41 | } 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /staging/etc/motd: -------------------------------------------------------------------------------- 1 | 2 | SELKS comes with ABSOLUTELY NO WARRANTY, to the extent 3 | permitted by applicable law. 4 | 5 | The programs included with the Debian GNU/Linux system are free software; 6 | the exact distribution terms for each program are described in the 7 | individual files in /usr/share/doc/*/copyright. 8 | 9 | Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent 10 | permitted by applicable law. 11 | _____ __ _ __ _____ ________ __ _______ 12 | / ___// /_____ _____ ___ __ _______/ | / / / ___// ____/ / / //_/ ___/ 13 | \__ \/ __/ __ `/ __ `__ \/ / / / ___/ |/ / \__ \/ __/ / / / ,< \__ \ 14 | ___/ / /_/ /_/ / / / / / / /_/ (__ ) /| / ___/ / /___/ /___/ /| |___/ / 15 | /____/\__/\__,_/_/ /_/ /_/\__,_/____/_/ |_/ /____/_____/_____/_/ |_/____/ 16 | 17 | -------------------------------------------------------------------------------- /staging/etc/profile.d/pythonpath.sh: -------------------------------------------------------------------------------- 1 | PYTHONPATH="/usr/lib/python2.7/site-packages/":"${PYTHONPATH}" 2 | export PYTHONPATH 3 | -------------------------------------------------------------------------------- /staging/etc/systemd/system/molochpcapread-selks.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Moloch Pcap Read 3 | After=network.target 4 | #Requires=network.target 5 | 6 | #After=network.target elasticsearch.service 7 | #Requires=network.target elasticsearch.service 8 | 9 | [Service] 10 | Type=simple 11 | #Restart=on-failure 12 | StandardOutput=tty 13 | #ExecStartPre=-/data/moloch/bin/moloch_config_interfaces.sh 14 | ExecStart=/bin/sh -c '/data/moloch/bin/moloch-capture -c /data/moloch/etc/config.ini -m -s -R /data/nsm/ >> /data/moloch/logs/capture.log 2>&1' 15 | WorkingDirectory=/data/moloch 16 | LimitCORE=infinity 17 | Restart=always 18 | RestartSec=90 19 | StartLimitInterval=600 20 | StartLimitBurst=4 21 | 22 | [Install] 23 | WantedBy=multi-user.target 24 | -------------------------------------------------------------------------------- /staging/etc/systemd/system/molochviewer-selks.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Moloch Viewer 3 | After=network.target 4 | 5 | [Service] 6 | Type=simple 7 | #Restart=on-failure 8 | StandardOutput=tty 9 | ExecStart=/bin/sh -c '/data/moloch/bin/node viewer.js -c /data/moloch/etc/config.ini >> /data/moloch/logs/viewer.log 2>&1' 10 | WorkingDirectory=/data/moloch/viewer 11 | Restart=always 12 | RestartSec=90 13 | StartLimitInterval=600 14 | StartLimitBurst=4 15 | 16 | [Install] 17 | WantedBy=multi-user.target 18 | -------------------------------------------------------------------------------- /staging/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StamusNetworks/SELKS/4af455cd15f69f2ba471fa6cd0b96d6aae6e93b9/staging/splash.png -------------------------------------------------------------------------------- /staging/usr/share/applications/Evebox.desktop: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env xdg-open 2 | [Desktop Entry] 3 | Version=1.0 4 | Name=EveBox 5 | Icon=applications-internet 6 | Comment=Launch-EveBox-Web-Access 7 | Exec=firefox-esr https://localhost/evebox/ 8 | Type=Application 9 | Categories=Application;System; 10 | StartupNotify=true 11 | Terminal=false 12 | 13 | -------------------------------------------------------------------------------- /staging/usr/share/applications/Scirius.desktop: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env xdg-open 2 | [Desktop Entry] 3 | Version=1.0 4 | Name=Scirius 5 | #Icon=preferences-other 6 | Icon=applications-internet 7 | Comment=Launch-Kibana-Web-Access 8 | Exec=firefox-esr https://localhost/rules/ 9 | Type=Application 10 | Categories=Application;System; 11 | StartupNotify=true 12 | Terminal=false 13 | 14 | -------------------------------------------------------------------------------- /staging/usr/share/polkit-1/actions/org.stamusnetworks.firsttimesetup.policy: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | Run the first time setup script as root 10 | Authentication is required to run SELKS First Time Setup 11 | 12 | auth_admin 13 | auth_admin 14 | auth_admin 15 | 16 | /usr/bin/selks-first-time-setup_stamus 17 | TRUE 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /staging/usr/share/polkit-1/actions/org.stamusnetworks.setupidsinterface.policy: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | Run Setup IDS interface as root 10 | Authentication is required to run Setup IDS interface 11 | 12 | auth_admin 13 | auth_admin 14 | auth_admin 15 | 16 | /usr/bin/selks-setup-ids-interface 17 | TRUE 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /staging/usr/share/polkit-1/actions/org.stamusnetworks.update.policy: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | Run SELKS upgrade as root 10 | Authentication is required to run SELKS upgrade 11 | 12 | auth_admin 13 | auth_admin 14 | auth_admin 15 | 16 | /usr/bin/selks-upgrade_stamus 17 | TRUE 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /staging/usr/share/polkit-1/rules.d/org.stamusnetworks.rules: -------------------------------------------------------------------------------- 1 | # Allow all users in the sudo group to run the SELKS setup scripts 2 | polkit.addRule(function(action, subject) { 3 | if ((action.id == "org.freedesktop.policykit.pkexec.run-selksfirsttimesetup" || action.id == "org.freedesktop.policykit.pkexec.run-selkssetupidsinterface" || action.id == "org.freedesktop.policykit.pkexec.run-selksupgrade") && subject.isInGroup("sudo")) { 4 | return polkit.Result.YES; 5 | } 6 | }); 7 | --------------------------------------------------------------------------------