appsettings.json

appsettings.json is the core configuration file of GZCTF, which is configured by mounting into the container. This document will introduce the meaning of each field in the configuration file.

INFO

You need to restart the GZCTF service every time you update appsettings.json to make it effective.

Structure of the configuration file

Here is a complete example of configuration:

{
  "AllowedHosts": "*",
  "ConnectionStrings": {
    "Database": "Host=db:5432;Database=gzctf;Username=postgres;Password=<Database Password>"
    // redis is optional
    // "RedisCache": "cache:6379,password=<Redis Password>",
    // external storage (minio s3, aws s3, azure blob) is optional, aws s3 for example
    // "Storage": "minio.s3://keyId=<YOUR_KEY_ID>;key=<YOUR_KEY>;bucket=<YOUR_BUCKET>;region=<YOUR_REGION>"
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    },
    "Loki": {
      "Enable": true,
      "EndpointUri": "http://loki:3100",
      "Labels": [
        {
          "Key": "app",
          "Value": "gzctf"
        }
      ],
      "PropertiesAsLabels": ["app"],
      "Credentials": {
        "Login": "login",
        "Password": "password"
      },
      "Tenant": "my-tenant",
      "MinimumLevel": "Trace"
    }
  },
  "Telemetry": {
    "Prometheus": {
      "Enable": false,
      "Port": 3000,
      "TotalNameSuffixForCounters": false
    },
    "OpenTelemetry": {
      "Enable": false,
      "Protocol": "Grpc",
      "EndpointUri": "http://jaeger-collector:4317"
    },
    "AzureMonitor": {
      "Enable": false,
      "ConnectionString": "InstrumentationKey=12345678-abcd-abcd-abcd-12345678..."
    },
    "Console": {
      "Enable": false
    }
  },
  "EmailConfig": {
    "SenderAddress": "",
    "SenderName": "",
    "UserName": "",
    "Password": "",
    "Smtp": {
      "Host": "localhost",
      "Port": 587,
      "BypassCertVerify": false
    }
  },
  "XorKey": "<Random Key Str>",
  "ContainerProvider": {
    "Type": "Docker", // or "Kubernetes"
    "PortMappingType": "Default",
    "EnableTrafficCapture": false,
    "PublicEntry": "ctf.example.com", // or "xxx.xxx.xxx.xxx"
    "DockerConfig": {
      // optional
      "SwarmMode": false,
      "ChallengeNetwork": "",
      "Uri": "unix:///var/run/docker.sock",
      "UserName": "",
      "Password": ""
    },
    "KubernetesConfig": {
      // optional
      "Namespace": "gzctf-challenges",
      "ConfigPath": "kube-config.yaml",
      "AllowCIDR": [
        // allow the cluster CIDR for LB
        "10.0.0.0/8"
      ],
      "DNS": [
        // custom DNS to avoid cluster DNS
        "8.8.8.8",
        "223.5.5.5"
      ]
    }
  },
  "RequestLogging": false,
  "DisableRateLimit": false,
  "RegistryConfig": {
    "UserName": "",
    "Password": "",
    "ServerAddress": ""
  },
  "CaptchaConfig": {
    "Provider": "None",
    "SiteKey": "...",
    "SecretKey": "...",
    // optional
    "GoogleRecaptcha": {
      "VerifyAPIAddress": "https://www.recaptcha.net/recaptcha/api/siteverify",
      "RecaptchaThreshold": "0.5"
    },
    // optional
    "HashPow": {
      "Difficulty": 18
    }
  },
  "ForwardedOptions": {
    "ForwardedHeaders": 7, // a flag enum, see following link
    "ForwardLimit": 1,
    "ForwardedForHeaderName": "X-Forwarded-For",
    // use the following options to allow proxy
    "TrustedNetworks": ["10.0.0.0/8"],
    "TrustedProxies": ["10.0.0.1"]
  },
  "Kestrel": {
    "Endpoints": {
      "Web": {
        "Url": "http://*:8080"
      },
      "Prometheus": {
        "Url": "http://*:3000"
      }
    },
    "Limits": {
      "MaxResponseBufferSize": 2048,
      "MaxRequestBufferSize": 1048576,
      "MaxRequestLineSize": 8192,
      "MaxRequestHeadersTotalSize": 32768,
      "MaxRequestHeaderCount": 100,
      "MaxRequestBodySize": 27262946,
      "KeepAliveTimeout": "0.0:5:0",
      "RequestHeadersTimeout": "0.0:5:0",
      "MaxConcurrentConnections": null,
      "MaxConcurrentUpgradedConnections": null
    },
    "AddServerHeader": true,
    "AllowResponseHeaderCompression": true,
    "AllowSynchronousIO": false,
    "AllowAlternateSchemes": false,
    "DisableStringReuse": false,
    "ConfigurationLoader": null
  }
}

Core configuration fields

ConnectionStrings

Here we can the configure the connection of the database.

Database

This field is required.

GZCTF uses PostgreSQL as the backend database and data persistence

INFO

GZCTF only supports PostgreSQL as the database, and does not support MySQL and other databases. Please fill in the correct database connection settings in the configuration file.

RedisCache

This field is optional.

GZCTF uses Redis as the cache and message queue. In the case of single instance deployment, Redis is not necessary, and GZCTF's memory cache can be used directly; in the case of multi-instance deployment, Redis is necessary as a shared cache and SignalR's Scale-Out broadcast.

In v1.0 and later, GZCTF supports using Garnet as the cache service.

Storage

This field is optional.

GZCTF supports external storage services like AWS S3 and Azure Blob Storage. You can configure the storage service to store files and other data.

  • MinIO S3

    minio.s3://keyId=...;key=...;bucket=...;region=...;serviceUrl=...

    • keyId: Optional. Access Key ID
    • key: Optional. Secret Access Key
    • bucket: Bucket name
    • region: Region (such as us-east-1)
    • serviceUrl: MinIO service URL
  • AWS S3

    aws.s3://keyId=...;key=...;bucket=...;region=...

    • keyId: Optional. Access Key ID
    • key: Optional. Secret Access Key
    • bucket: Bucket name
    • region: Region (such as us-east-1)
    • serviceUrl: Optional. URL of the storage provider (for example for DigitalOcean).
  • Azure Blob

    azure.file://account=...;key=...

    For more information, checkout Quickstart: Azure Blob Storage client library for .NET

For more information, see the following links:

If you want to use more FluentStorage providers, please open an issue.

Logging

You can configure the logging level and scopes, besides, GZCTF also supports sending logs to Loki server.

  • LogLevel: The minimal logging level per namespace.

  • Loki: The configuration of Loki server.

    • Enable: Enable it or not.
    • EndpointUri: The URI of Loki server.
    • Labels: Optional. The global log event labels.
    • PropertiesAsLabels: Optional. The list of properties, which should be mapped to Loki labels.
    • Credentials: Optional. Credentials, which will be used for basic auth
    • Tenant: Optional. The Tenant ID used for sending logs to Loki server.
    • MinimumLevel: Optional. Minimal logging level.

Available logging levels: Trace, Debug, Information, Warning, Error, Critical, None.

Telemetry

GZCTF supports metrics and distributed tracing. You can configure the providers you want to use.

  • Prometheus: Prometheus endpoint support.

    • Enable: Enable it or not.
    • Port: Optional. Set the port that Prometheus /metrics endpoint listens on. If this is configured, additional manual configuration of Kestrel.Endpoints is required to make the server listen to the specified port normally.
    • TotalNameSuffixForCounters: Optional. Whether to include _total suffix in counters or not.
  • OpenTelemetry: Exporting metrics and tracing data to OpenTelemetry.

    • Enable: Enable it or not.
    • Protocol: Grpc or HttpProtobuf.
    • EndpointUri: The OpenTelemetry endpoint URI to push telemetry data.
  • AzureMonitor: Exporting metrics and tracing data to ApplicationInsights.

    • Enable: Enable it or not.
    • ConnectionString: The connection string.
  • Console: Exporting tracing data to console.

    • Enable: Enable it or not.

EmailConfig

Here we can configure the information of email sending server. If you use email registration and other email features, this is required.

  • SenderAddress: Email address of the sender
  • SenderName: Name of the sender
  • UserName: SMTP Server username
  • Password: SMTP Server password
  • Smtp: SMTP Server address and port
  • BypassCertVerify: Whether to bypass the certificate verification of the SMTP server
INFO

Some cloud service provider may block port 465, please try port 587.

XorKey

Here we can configure the encryption key for encrypting the private key of the competition in the database. It can string of any length.

ContainerProvider

Heer we can configure the container backend which is required for creating containers dynamically during the game.

  • Type: Type of the container backend: Docker or Kubernetes
  • PublicEntry: Public entry of the container backend, used to generate the address of the competition, and show to the participating teams.
  • PortMappingType: Port mapping type, can be Default or PlatformProxy
  • EnableTrafficCapture: Enable/Disable traffic capture, only available when PortMappingType is configured as PlatformProxy. Captured traffic will be saved to /app/files/capture.

Docker

  • SwarmMode: Use Swarm mode, GZCTF will use Swarm API to manage the containers if this is enabled.
WARNING

Since Docker Swarm is no longer an active project, security features are far behind k8s, and it is not recommended.

  • Uri: Docker API Server Address

    • If you use local docker, please leave Uri empty, and mount /var/run/docker.sock into the container.
    • If you use external docker, please set Uri to the corresponding docker API Server, external API authentication has not been implemented, this deployment method is not recommended
  • ChallengeNetwork: Specify the network where the challenge container is located. If not specified, the default network will be used.

  • UserName, Password: Docker API Basic Auth username and password, optional.

Kubernetes

  • Namespace: Kubernetes namespace, used to create the namespace of the challenge instance, the default is gzctf-challenges
  • ConfigPath: Kubernetes configuration file path, used to connect to the cluster, default value is kube-config.yaml
  • AllowCIDR: White list of CIDR that can access the Pod
  • DNS: custom DNS server list

To use the default behavior, please put the cluster connection configuration into the kube-config.yaml file and mount it to the /app directory. Do not change it if you don't understand the behavior of the experimental function.

INFO

Please note that you need to change the server field in the kube-config.yaml file to point to the API Server address of the cluster. The default address of the cluster is generally https://127.0.0.1:6443, which needs to be changed to the actual address of the cluster.

INFO

In order to meet the network policy, GZCTF will create a NetworkPolicy named gzctf-policy in the Namespace of the challenge to restrict access. GZCTF will automatically detect whether this NetworkPolicy already exists. If it exists, it will not be created again, so you can customize the network policy by creating or editing this NetworkPolicy.

RequestLogging

Enable/Disable request logging, if enabled, detailed information of each request will be appended to the log. Static file requests are not included in the output here.

DisableRateLimit

Enable/Disable request rate limit, if enabled, the request rate of each IP and API will be limited according to the preset rules.

RegistryConfig

Here we can configure the username and password of the Docker Registry, which is used to pull the container image for dynamic container during the game.

  • UserName: User name of the Docker Registry
  • Password: Password of the Docker Registry
  • ServerAddress: Address of the Docker Registry, please note that the https:// prefix is not required
INFO

Please make sure that the password does not contain special characters (such as ":@ etc., but _ can be used), otherwise it may cause template injection problems and make Secret not work properly.

CaptchaConfig

Configure the Captcha used for user registration, account recovery and login, optional.

  • Provider: Captcha provider, can be None, HashPow, GoogleRecaptcha or CloudflareTurnstile
  • SiteKey: Captcha Sitekey
  • SecretKey: Captcha Secretkey

HashPow

Configure the HashPow captcha related information, optional.

INFO

Secure context: This feature is available only in secure contexts (HTTPS).

  • Difficulty: Difficulty of HashPow captcha, used to specify the number of leading zeros in the hash bits. The avaliable range is from 8 to 48.

GoogleRecaptcha

Configure the Google Recaptcha v3 related information, optional.

  • VerifyAPIAddress: Google Recaptcha verify API address
  • RecaptchaThreshold: Google Recaptcha threshold, used to determine whether the captcha is effective

ForwardedOptions

Here we can configure the reverse proxy, which is used to get the real IP address, optional.

  • ForwardedHeaders: Enum for ForwardedHeaders in reverse proxy, please use 7 as the default value. For more details, see ForwardedHeaders Enum
  • ForwardLimit: Limit the number of proxy hops allowed, the default is 1
  • ForwardedForHeaderName: The name of the reverse proxy IP address header
  • TrustedNetworks: List of trusted networks for reverse proxy, represented by CIDR.
  • TrustedProxies: List of trusted proxies for reverse proxy, represented by IP addresses or domain names.
INFO

If you want to ignore the trust list of reverse proxies and allow any IP address to access, please refer to the solution for forwarding Linux and non-IIS reverse proxies, and set the environment variable ASPNETCORE_FORWARDEDHEADERS_ENABLED to true.

For other fields, please refer to the official documentation: Configure ASP.NET Core to work with proxy servers and load balancers and ForwardedHeadersOptions class

Kestrel

Kestrel is the built-in web server used by GZCTF. With this configuration, you can control the behavior of Kestrel, such as specifying the HTTP protocol, modifying the request size limit, and more.

  • Endpoints: Configure the URL that the web server listens on.
  • For other configurable fields, please refer to the properties of the KestrelServerOptions class in the official documentation: KestrelServerOptions class