Skip to content

nerou42/network-journal

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

48 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

network-journal

GitHub Actions Workflow Status GitHub Release

This project is about handling all the reports browsers (Content Security Policy, Network Error Logging etc.) and e-mail servers (DMARC, SMTP TLS etc.) can send nowadays.

To do that, this project contains a webserver, that will listen to incoming reports, validate them, filter them, structure them and log them to a file. This log file can be read by your log monitoring tools like an ELK-stack or Grafana Loki. With that, you can generate diagrams, configure alerts, you name it.

flowchart LR
    browser("Browser") e1@-- CSP, NEL, Permission etc. reports ---> webserver
    mailserver("E-Mail server") e2@-- SMTP TLS reports --> webserver
    mailserver e3@-- DMARC reports --> mailbox("Mailbox")
    mailbox e4@--> imap
    
    subgraph "network-journal"
        webserver("Webserver") e11@--> processing("Processing
        (filter, derive etc.)")
        imap("IMAP client") e12@--> processing
        processing e13@--> logfile("Log file")
    end
    
    subgraph "ELK-stack/Grafana Loki/..."
        logfile e21@--> monitoring("Log file 
        parser")
        monitoring e22@--> visualization("Visualization")
        monitoring e23@--> alerting("Alerting")
    end

    e1@{ animation: slow }
    e2@{ animation: slow }
    e3@{ animation: slow }
    e4@{ animation: slow }
    e11@{ animation: slow }
    e12@{ animation: slow }
    e13@{ animation: slow }
    e21@{ animation: slow }
    e22@{ animation: slow }
    e23@{ animation: slow }
Loading

Current State

Supported Reports

Supported Report Handling

  • Webserver listening to incoming reports
  • Report validation
  • Filtering by your own domains to prevent spam
  • Derive additional metrics from...
    • user agent (browser name and version, OS name and version etc.)
    • origin/document URLs (host, path, query)
  • Log reports to file

Supported Installation Methods

Install

Run the executable once (with the --config parameter set to a path of your liking) to generate the default configuration file.

Note: Some reporters require TLS to be enabled. If you are using some reverse proxy on the other hand, you do not need to enable TLS in this context but on your proxy.

Configure your reports

In the following, network-journal.example.com needs to be replaced with your network-journal domain while example.com needs to be replaced with your frontend or e-mail domain respectively.

Note: All Reporting-Endpoints headers discussed below should be combined into one like so Reporting-Endpoints: crash-reporting="...", "csp-endpoint="..." or even Reporting-Endpoints: default="https://network-journal.example.com/reporting-api". The same should be done for the Report-To header like so Report-To: {"group": ...}, {"group": ...}.

COEP

Add the following HTTP headers to your HTTP responses:

  1. Cross-Origin-Embedder-Policy: [...]; report-to="coep"
  2. Report-To: {"group": "coep", "max_age": 2592000, "endpoints": [{ "url": "https://network-journal.example.com/reporting-api" }]}

COOP

Add the following HTTP headers to your HTTP responses:

  1. Cross-Origin-Opener-Policy: [...]; report-to="coop"
  2. Report-To: {"group": "coop", "max_age": 2592000, "endpoints": [{ "url": "https://network-journal.example.com/reporting-api" }]}

Crash

Add the following HTTP header to your HTTP responses:

Reporting-Endpoints: crash-reporting="https://network-journal.example.com/reporting-api"

CSP (Content Security Policy)

Add the following HTTP headers to your HTTP responses:

  1. Reporting-Endpoints: csp-endpoint="https://network-journal.example.com/reporting-api"
  2. Content-Security-Policy: [...]; report-to csp-endpoint Since report-to is not yet supported by all browsers, you probably should do the following instead: Content-Security-Policy: [...]; report-to csp-endpoint; report-uri https://network-journal.example.com/csp

Deprecation

Add the following HTTP header to your HTTP responses:

Reporting-Endpoints: default="https://network-journal.example.com/reporting-api"

Note: At time of writing, deprecation reports are always delivered to the "default" endpoint.

DMARC

Add a DMARC DNS entry with a rua tag to send aggregate reports to some mailbox (it is recommended to create a mailbox solely for this purpose). Set the credentials for this mailbox in the configuration file.

Integrity Policy

Add the following HTTP header to your HTTP responses:

Reporting-Endpoints: integrity-endpoint="https://network-journal.example.com/reporting-api"

Note: You could also define a different endpoint and link it to your Integrity-Policy header using the Integrity-Policy: blocked-destinations=..., endpoints="my-integrity-endpoint" syntax.

Intervention Policy

Add the following HTTP header to your HTTP responses:

Reporting-Endpoints: default="https://network-journal.example.com/reporting-api"

Note: At time of writing, intervention reports are always delivered to the "default" endpoint.

NEL (Network Error Logging)

Add the following HTTP headers to your HTTP responses:

  1. Report-To: { "group": "nel", "max_age": 31556952, "endpoints": [{ "url": "https://network-journal.example.com/nel" }]} (deprecated) or Reporting-Endpoints: nel="https://network-journal.example.com/reporting-api" (not yet supported by all browsers)
  2. NEL: { "report_to": "nel", "max_age": 31536000, "include_subdomains": true }

SMTP TLS

Add the following DNS entry for your domain:

_smtp._tls.example.com IN TXT "v=TLSRPTv1; rua=https://network-journal.example.com/tlsrpt"

Log Format

The received reports are logged in the following format:

2025-08-06T14:15:16.123Z INFO [network-journal::<module>] <report_type> <report-content-as-json>

where <report_type> can be one of:

  • COEP
  • COOP
  • Crash
  • CSP
  • CSP-Hash
  • Deprecation
  • DMARC
  • IntegrityViolation
  • Intervention
  • NEL
  • PermissionsPolicyViolation
  • SMTP-TLS-RPT

and where <report-content-as-json> looks like this (using a CSP level 3 report as an example here):

{
    "report": {
        "age": 53531,
        "body": {
            "blockedURL": "inline",
            "columnNumber": 39,
            "disposition": "enforce",
            "documentURL": "https://example.com/csp-report",
            "effectiveDirective": "script-src-elem",
            "lineNumber": 121,
            "originalPolicy": "default-src 'self'; report-to csp-endpoint-name",
            "referrer": "https://www.google.com/",
            "sample": "console.log(\"lo\")",
            "sourceFile": "https://example.com/csp-report",
            "statusCode": 200
        },
        "type": "csp-violation",
        "url": "https://example.com/csp-report",
        "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36"
    },
    "derived": {
        "client": {
            "family": "Chrome",
            "major": 127,
            "minor": 0,
            "patch": 0,
            "patch_minor": 0
        },
        "os": {
            "family": "Windows",
            "major": 10,
            "minor": 0
        },
        "device": {
            "family": "other"
        },
        "url": {
            "host": "example.com",
            "path": "/csp-report",
            "query": ""
        }
    }
}

Log Levels

All reports are logged at the INFO level. If you observe relevant log entries e.g. at the DEBUG (payload validation errors are logged by actix at this level) or ERROR, please let me know by filing an issue on GitHub.

License

This project is licensed under the GPLv3.0 license.