OxidProxy — User Guide

Document version: 1.11
Software version: 2.4.1
Website: https://oxidproxy.com
Support: support@oxidproxy.com · Telegram

TipYou do not have to read any of this. Hand the AI agent instruction to any agent with SSH access to the server — it will ask what it needs and deploy the server itself. The guide below is for later, when you want to understand the settings.

Contents

  1. Product overview
  2. System requirements
  3. Installation
  4. Initial setup
  5. Configuration (config.yaml)
    - 5.1 Licensing
    - 5.2 Network settings
    - 5.3 OS fingerprinting
    - 5.4 IPv6 subnets and rotation
    - 5.5 API and user management
    - 5.6 DNS resolver
    - 5.7 Traffic shaping
    - 5.8 Timeouts
    - 5.9 Service account
    - 5.10 Blacklist
    - 5.11 Logging
    - 5.12 MITM mode (mitm_listeners)
    - 5.13 Dashboard branding
  6. HTTP API
  7. Web dashboard
  8. Service management
  9. Logging and monitoring
  10. Command line (CLI)
  11. Troubleshooting
  12. FAQ
  13. Changelog

1. Product overview

OxidProxy is a high-performance SOCKS5(h) / HTTP CONNECT IPv6 proxy server written in Rust. It is meant to run on your own dedicated or virtual server and acts as a gateway: it accepts incoming connections over IPv4, authenticates them and routes traffic through the IPv6 subnets you configure.

Key features

Feature Description
SOCKS5 / SOCKS5h Full protocol support, including remote DNS, which prevents DNS leaks
HTTP CONNECT HTTP(S) proxy mode via the CONNECT method, for browsers, curl and system proxy settings
Hybrid Mode Automatic protocol detection (SOCKS5 or HTTP) on a single port
UDP / QUIC Full UDP proxying, including QUIC (HTTP/3)
Multiple subnets Attach several IPv6 subnets and balance between them by weight
Lazy rotation The IP changes only on re-authentication; active sessions are never dropped
Smart DNS Failover Built-in resolver with balancing and automatic failover to backup servers
OS Fingerprinting (p0f) TCP/IP fingerprint masking as Linux, Android, Windows, iOS or macOS
Traffic Shaping Total bandwidth limiting with burst support
HTTP(S) API Instant credential generation, statistics and management over a REST API
IP Whitelist Manage allowed addresses and subnets from the dashboard; system entries are protected
Web dashboard Built-in monitoring panel with traffic charts, connection analytics and selectable themes
Blacklist Block domains and IP addresses through blacklist.txt
Service account A restricted account intended for checkers and monitoring

How it works

   Your software      OxidProxy Server           IPv6 subnets         Internet
  (SOCKS5h/HTTP)  →   Auth • DNS • Shaping   →  Subnet A (w:100)  →  Target
                                                 Subnet B (w:50)
ImportantFor maximum anonymity your client must use SOCKS5h (remote DNS). In that mode DNS queries are resolved on the OxidProxy server rather than on your own machine.
NoteOxidProxy routes traffic over IPv6 only. The target resource must support IPv6.

2. System requirements

Item Minimum Recommended
OS Debian 12 (Bookworm) x64 Debian 12 (Bookworm) x64
CPU 1 core 2 or more cores
RAM 512 MB 1 GB or more, depending on max_accounts
IPv6 a /64 subnet a /48 or /32 subnet
Privileges root, for installation The service itself runs as the oxidproxy user
NoteOS fingerprint masking (p0f) requires the custom kernel 6.1.177-oxidproxy-p0f. Without it every other feature still works normally.

3. Installation

ImportantInstall OxidProxy on a clean, fully updated Debian 12 (Bookworm). The custom kernel shipped with the server provides OS fingerprinting, but it is not universal: on some hardware the required drivers may be missing and the machine will not boot after the kernel is installed. If the server does not come back after a reboot, contact support at support@oxidproxy.com or on Telegram.

Run as root:

curl -fsSL https://oxidproxy.com/downloads/install.sh | bash

The script will:
1. Download and install the custom Linux kernel with the p0f patch
2. Configure GRUB to boot the new kernel by default
3. Download and install the OxidProxy package
4. Create the oxidproxy system user
5. Set up the systemd service
6. Offer to reboot the server

3.2. Manual installation

  1. Download the .deb package from the downloads page
  2. Install the package:
dpkg -i oxidproxy_*.deb
# If dependencies fail:
apt-get install -f -y
  1. Optionally, install the custom kernel for p0f:
dpkg -i linux-image-6.1.177-oxidproxy-p0f_6.1.177-oxidproxy-p0f-1_amd64.deb
update-grub
NoteThe linux-headers package for 6.1.177-oxidproxy-p0f is available on the downloads page. It is needed to build out-of-tree kernel modules.

3.3. What the installer creates

Path Purpose
/usr/bin/oxidproxy The executable
/etc/oxidproxy/config.yaml Main configuration file
/etc/oxidproxy/blacklist.txt List of blocked domains and addresses
/etc/oxidproxy/whitelist.txt Whitelist of allowed addresses and subnets
/etc/rc.local IPv6 routing rules; created during installation if absent
/etc/sysctl.d/90-oxidproxy.conf Kernel settings (sysctl)
/usr/lib/systemd/system/oxidproxy.service systemd unit file
/etc/logrotate.d/oxidproxy Log rotation configuration
/var/log/oxidproxy/ Log directory
/var/lib/oxidproxy/ Data directory, used for exported accounts

4. Initial setup

The service does not start automatically after installation. Complete these steps first:

The server checks these values when it starts. If license_key, master_token or public_ip still hold the values from the template, the service says which one and does not start, so a half-configured server never goes live.

Step 1. Edit the configuration

nano /etc/oxidproxy/config.yaml

These must be filled in:
- license_key — your licence key, obtained via Telegram
- public_ip — the external IPv4 address of your server
- ipv6_subnets — your IPv6 subnets
- master_token — the secret API token; replace the default

Step 2. Set up IPv6 routing

Edit /etc/rc.local and uncomment the route line:

nano /etc/rc.local

Replace the placeholder with your real subnet:

ip -6 route add local 2a01:xxxx::/32 dev lo
CautionWithout correct IPv6 routing the proxy cannot bind to addresses from the configured subnets.

Step 3. Validate the configuration

oxidproxy -t /etc/oxidproxy/config.yaml

It should print ✅ Syntax OK. followed by a summary of the main settings.

Step 4. Reboot the server

reboot

Required to activate the custom kernel and the routing rules.

Step 5. Start the service

systemctl start oxidproxy
systemctl status oxidproxy

5. Configuration (config.yaml)

Every setting lives in /etc/oxidproxy/config.yaml. Restart the service to apply changes.

TipAlways validate the configuration with oxidproxy -t before restarting.

5.1. Licensing

license_key: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"

# license_servers: optional - see the note below
Parameter Description
license_key Required. The licence key you received on purchase
license_servers Optional. The regular endpoints are built into the server, so there is nothing to set here. Fill it in only with an address given to you by support, for instance when the usual endpoints are unreachable from your network. Entries here are tried first.
Note

About the licence server addresses. They no longer belong in the config: they are built into the server and spread across two independently registered domains, so that one becoming unreachable does not stop licence checks.

The license_servers parameter is needed in one case only: support has given you a dedicated address. Such addresses are tried before the built-in ones, so a working endpoint takes effect immediately, without waiting through timeouts on unreachable ones.

license_servers:
  - "address.given.by.support:8000"

Order of attempts: addresses from the config first, if any, then the built-in ones. A server that answers successfully moves to the front of the list and is used for subsequent checks.

ImportantThe server will not start without a valid licence. To check a specific endpoint, run oxidproxy --ping address:port — useful when support has given you a dedicated address and you want to confirm it is reachable from your network. The built-in endpoints need no manual checking; the server walks them itself.

5.2. Network settings

listen_ip: "0.0.0.0"
public_ip: "123.45.67.89"
# ext_iface: "eth0"  # optional
Parameter Description Default
listen_ip Interface to accept incoming connections on 0.0.0.0 (all interfaces)
public_ip Required. Public IPv4 address of the server, used by the API and in generated links
ext_iface External interface used for QoS. Detected automatically when not set auto

5.3. OS fingerprinting

The listeners section defines several ports, each with its own TCP/IP fingerprint profile. Anti-fraud systems that inspect traffic with tools such as p0f will see the parameters characteristic of the chosen operating system.

Every listener supports a mode field that selects the protocol:

Mode Description
socks SOCKS5 / SOCKS5h (default)
http HTTP CONNECT proxy, using the CONNECT method with Proxy-Authorization: Basic
hybrid Auto-detect: SOCKS5 and HTTP on one port. The protocol is determined from the first byte
listeners:
  - port: 1080
    os_preset: "linux"
    # mode: "socks"  # the default, may be omitted

  - port: 1081
    os_preset: "android"
    mode: "hybrid"    # accepts both SOCKS5 and HTTP CONNECT

  - port: 1082
    os_preset: "windows"
    mode: "http"

  - port: 1083
    os_preset: "ios"
    mode: "socks"

  - port: 1084
    os_preset: "macos"
    mode: "http"
Tiphybrid is the recommended mode. One port serves both protocols, so no extra ports need opening, and detection is instant, from the first byte.

Available profiles:

Profile TTL TCP MSS Congestion Control Description
linux 64 System default cubic A standard Linux server
android 64 Common for the platform bbr A mobile Android client
windows 128 Common for the platform cubic A Windows machine
ios 64 Common for the platform cubic iPhone / iPad
macos 64 Common for the platform cubic A macOS desktop
NoteTCP MSS is not a fixed number. For every profile that emulates an operating system, the value is chosen from those common on the networks that platform is normally used on, and tied to the specific outgoing IPv6 address. It does not change within a session, so behaviour stays predictable. When the address rotates the value may change — exactly as it does on a real device moving between networks. The linux profile emulates nothing and keeps the system value.

Fine-tuning (for experienced users only):

Each listener accepts manual network parameters:

  - port: 1081
    os_preset: "android"
    tcp_congestion: "bbr"      # congestion control algorithm
    tcp_window_size: 1048576   # TCP window size, bytes
    latency_base_ms: 60        # base latency, ms
    jitter_ms: 30              # jitter, ms
    tos: 10                    # traffic class (QoS marker)
CautionChanging the fine-tuning parameters without understanding them can destabilise the server or weaken the masking. If in doubt, leave the defaults alone.

5.4. IPv6 subnets and rotation

ipv6_subnets:
  - cidr: "2a01:xxxx::/32"
    weight: 427
  - cidr: "2a02:yyyy:yyyy:yyyy::/64"
    weight: 16

rotation_interval: 10
Parameter Description
cidr IPv6 subnet in CIDR notation. Any size is supported: /29, /32, /48, /64 and so on
weight Subnet weight. The higher the value, the more often the subnet is used for outgoing addresses
rotation_interval Rotation interval in minutes. 0 disables rotation, and the IP is kept until restart

How rotation works:
- The IP address is bound to a login and password pair (a sticky session)
- On every authentication the server checks whether rotation_interval has elapsed
- If it has, a new IPv6 is generated from the subnets, honouring their weights
- Active connections are never dropped — the IP changes only on a new connection
- A session idle for more than 5 minutes is closed; this is tunable via timeouts.idle

TipExample: if subnet A has weight 100 and subnet B has weight 50, subnet A will supply addresses twice as often.

5.5. API and user management

api_port: 8080
api_port_https: 8443  # optional - HTTPS API

master_token: "my-secret-token"

max_accounts: 100000

accounts_file: "/var/lib/oxidproxy/accounts_[port]_[os]_[mode].txt"

# account_seed: 123456789
Parameter Description Default
api_port HTTP API port 8080
api_port_https HTTPS API port (optional)
master_token Required. Secret token used to authenticate API requests
max_accounts Maximum number of unique accounts generated, each with its own IPv6 100000
accounts_file Path for exported accounts. Supports the [port], [os] and [mode] macros accounts.txt
account_seed Generation seed. With the same seed, logins and passwords stay identical across restarts random
TipUse account_seed when accounts must stay the same across restarts. This helps when integrating with external systems, as credentials never need updating.

5.6. DNS resolver

Names are resolved by the server itself. One cache is shared by all listeners, so a name looked up for one client is already resolved for the next. Servers carrying a weight share the load between them; those without one are used only when the weighted ones do not answer. The resolver keeps track of how each server behaves and stops sending queries to one that stopped answering, returning to it a little later. When the first server is slow, the next is queried in parallel and the first answer wins, so a single slow server does not hold the client up.

timeout is what a single server is given to answer, not what the client waits: with the parallel query above the client normally gets an answer sooner. Its job is to decide how quickly a server that went quiet is taken out of rotation, so it is kept short. Raise it to 2 if healthy servers are being taken out. What each server is doing right now is visible in /stats, section 6.2.

dns:
  timeout: 1
  cache_size: 8000
  suppress_aaaa_not_found: true

  servers:
    # primary servers (balanced)
    - address: "[2606:4700:4700::1111]:53"
      weight: 53
    - address: "1.1.1.1:53"
      weight: 7

    # failover servers
    - address: "[2620:fe::fe]:53"
    - address: "9.9.9.9:53"
Parameter Description Default
timeout DNS query timeout, in seconds 2
cache_size Number of cached DNS records 1024
suppress_aaaa_not_found Suppress warnings about domains that have no AAAA record false

How it works:
1. The query goes to one of the primary servers, chosen by weight — the higher the weight, the more often that server is used. There may be several primaries.
2. If a primary does not answer, whether by timeout or error, the query falls through to the failover pool. There may be several of those too; they are listed without a weight.
3. A domain that exists but has no AAAA record is not a connection error, so failover is not triggered

TipRecommended: add your hosting provider's resolvers with a high weight. Their addresses are usually in /etc/resolv.conf, or can be obtained from the provider's support. Provider resolvers typically answer in 1–2 ms, against 10–50 ms for Google or Cloudflare.

5.7. Traffic shaping

shaping:
  rate: 12500000   # 100 Mbit/s
  burst: 25000000  # 200 Mbit/s burst
Parameter Description
rate Maximum rate in bytes per second. 0 means unlimited
burst Burst allowance in bytes, letting transfers briefly exceed rate
NoteThe limit applies to the server as a whole — all users, both directions. The same figure is enforced separately for upload and download.

Cheat sheet:

Speed rate value
1 Mbit/s 125 000
10 Mbit/s 1 250 000
100 Mbit/s 12 500 000
1 Gbit/s 125 000 000

5.8. Timeouts

timeouts:
  shutdown: 10    # how long to wait for sessions to finish on shutdown, sec
  idle: 300       # maximum session idle time, sec
Parameter Description Default
shutdown How long, in seconds, to wait for active connections to finish when the service stops or restarts 15
idle Maximum idle time of a TCP or UDP session before it is closed 300 (5 min)

5.9. Service account

service_account:
  enabled: true
  login: "checker"
  password: "strong_password"
  allowed_domain: "ifconfig.me"

The service account is meant for monitoring and health checks. Its properties:
- Static login and password: neither generated nor rotated
- Can reach only one domain, set by allowed_domain
- Does not consume rotation limits
- Never changes its IP

TipIdeal for external checkers: set allowed_domain: "ifconfig.me" and verify the outgoing IP with curl --proxy socks5://checker:password@IP:PORT ifconfig.me.

5.10. Blacklist

blocked_file: "/etc/oxidproxy/blacklist.txt"

The file lists blocked domains and IP addresses, one per line. Comments start with #.

# blocking ad domains
doubleclick.net
ads.google.com

# blocking private IPv6 networks
fc00::/7
fe80::/10
ImportantBlocking covers subdomains. If google.com is blocked, then mail.google.com and ads.google.com are unreachable as well.

5.11. Logging

log:
  dir: "/var/log/oxidproxy"
  level: "info"
Level Description
error Critical errors only
warn Errors and warnings
info Main events: connections, DNS, rotation — recommended
debug Verbose debugging: every session, every DNS query

Two log files are produced:
- oxidproxy.log — the full log, at the verbosity set by level
- error.log — errors only, always

Note

Journal-only logging. The dir parameter is optional. Leave it empty, or drop it altogether, and no files are written to disk: everything goes to the system journal, where journalctl -u oxidproxy picks it up.

log:
  dir: ""        # empty = journal only
  level: "info"

This suits setups where journald already collects everything and a second copy on disk is unwanted. The log section may be omitted entirely, in which case the level defaults to info.

To confirm: oxidproxy -t /etc/oxidproxy/config.yaml reports Log Dir: not set, logging to journal only.

5.12. MITM mode (mitm_listeners)

In MITM mode OxidProxy terminates the client TLS connection with its own certificate authority and rebuilds the request to the target with the network fingerprint of a real browser: JA4 in full, HTTP/2 and Akamai. The profile is chosen automatically from the client User-Agent, so one port serves every OS and browser — Chrome, Firefox and Safari on Windows, macOS, Linux, Android and iOS.

MITM listeners are declared in their own mitm_listeners section and run alongside the regular listeners:

mitm_listeners:
  - port: 8443
    profiles:
      - "windows-chrome"
      - "windows-firefox"
      - "macos-safari"
      - "android-chrome"
      - "ios-safari"
    default: "windows-chrome"    # profile used when the client UA is not recognised
    # strict: false   # true = refuse instead of falling back to default
    # mode: socks      # socks / http / hybrid, as for regular listeners

Profiles are named <os>-<browser>. The available ones are:

OS Profiles
Windows windows-chrome, windows-firefox, windows-edge
macOS macos-chrome, macos-firefox, macos-safari
Linux linux-chrome, linux-firefox
Android android-chrome, android-firefox
iOS ios-safari

Listener fields:

Parameter Description
port Port of the MITM listener
profiles List of allowed <os>-<browser> profiles. The right one is chosen from the client User-Agent
default Profile used when the User-Agent is unrecognised or not in the list
strict When true, refuse the connection on a mismatch instead of falling back to default. Defaults to false
mode Listener protocol: socks (the default), http or hybrid, exactly as for regular listeners. When omitted, the port runs in socks mode.
ImportantBecause TLS is terminated with our own CA, the client must add the server CA certificate to its trust store once; otherwise the browser reports a certificate error. The CA can be downloaded from the server at the /ca endpoint.

5.13. Dashboard branding

The web dashboard can carry your own mark instead of ours. This exists for resellers: a customer's panel has no business advertising the vendor behind it.

brand:
  name:   "Acme"
  accent: "Proxy"
  url:    "https://acme.example"
Parameter Description
name First half of the wordmark, shown in the main text colour
accent Second half, painted in the accent colour of whichever theme is selected. Leave empty for a single-colour wordmark
url Where the wordmark links to. An empty value drops the link entirely. Only http:// and https:// are accepted

The setting reaches further than the header. It also renames the browser tab, the theme label in the selector, and the CA certificate the dashboard offers for download — that file is handed to end users, so a leftover name there would give the game away.

NoteThe section is optional. Omit it and the panel carries the OxidProxy mark, as it did before. The two halves of the name together may not exceed 64 characters.

6. HTTP API

The API is reachable at http://YOUR_IP:PORT or https://YOUR_IP:PORT, where PORT comes from api_port and api_port_https in the configuration, 8080 and 8443 by default.

Requests are authenticated with the token parameter, whose value is master_token.

Every endpoint answers with a standard HTTP status: 200 when the request succeeded, 401 when the token is missing or wrong, 400 when the request cannot be satisfied as written — for example a mode the listener does not serve — and 500 when the server cannot answer, such as a configuration with no listeners at all. The explanation is in the body; the status is what a script should branch on.

6.1. New credentials — GET /allocate

Returns a connection string with a fresh login and password. The listener is selected by port — the same URL the dashboard produces (section 7.6):

curl "http://YOUR_IP:8080/allocate?token=YOUR_TOKEN&port=1080&mode=socks5"

Response:

socks5://user_AbCdEfGh:KlMnOpQrSt@YOUR_IP:1080

Query parameters:

Parameter Description Default
token Required. The secret master_token
port Port of the listener the credentials are for. Identifies the listener unambiguously
mode Protocol: socks5 or http socks5
os OS profile: linux, android, windows, ios, macos. Selects the listener by profile; ignored when port is given linux

The port identifies the listener unambiguously. os selects it by profile; when several listeners share that profile, the first one in the configuration is returned. A port or profile that is not in the configuration is answered with 400 and a list of what is configured.

Examples:

# Credentials for the listener on port 1081
curl "http://YOUR_IP:8080/allocate?token=YOUR_TOKEN&port=1081&mode=socks5"
# response: socks5://user_xxx:pass_xxx@YOUR_IP:1081

# Same listener, HTTP proxy (listener in http or hybrid mode)
curl "http://YOUR_IP:8080/allocate?token=YOUR_TOKEN&port=1081&mode=http"
# response: http://user_xxx:pass_xxx@YOUR_IP:1081

# By OS profile
curl "http://YOUR_IP:8080/allocate?token=YOUR_TOKEN&os=android"
NoteA port that is not in the configuration, or a protocol the listener does not support, is rejected with 400:
Error: no listener on port 1090. Configured ports: 1080, 1081, 1082
Error: http mode is not enabled for 'linux' profile (port 1080). Listener mode: socks
TipIn hybrid mode both mode=socks5 and mode=http work on the same port.

6.2. Statistics — GET /stats

Returns full server statistics as JSON.

curl "http://YOUR_IP:8080/stats?token=YOUR_TOKEN"

Example response, abridged: the listeners and mitm_listeners fields are omitted, being an echo of the matching config sections.

{
  "version": "2.0.0",
  "uptime_seconds": 9980,
  "active_connections": { "tcp": 56, "udp": 4 },
  "mitm": { "active": 3, "total": 512 },
  "traffic": {
    "ingress_bytes": 264074969,
    "egress_bytes": 35524983
  },
  "dns": {
    "total_queries": 18905,
    "cache_hits": 17106,
    "cache_stale_served": 12,
    "cache_misses": 1799,
    "cache_entries": 1420,
    "inflight_joined": 63,
    "hedge_fired": 208,
    "hedge_won_by_backup": 41,
    "all_failed": 3,
    "bad_names": 0,
    "servers": [
      {
        "address": "[2606:4700:4700::1111]:53",
        "weight": 53, "state": "healthy",
        "queries": 1502, "failures": 7,
        "timeouts": 6, "servfails": 1, "net_errors": 0,
        "consecutive_failures": 0,
        "last_failure_ago_s": 1840, "last_error": "Timeout"
      },
      {
        "address": "1.1.1.1:53",
        "weight": 7, "state": "healthy",
        "queries": 261, "failures": 0,
        "timeouts": 0, "servfails": 0, "net_errors": 0,
        "consecutive_failures": 0,
        "last_failure_ago_s": null, "last_error": null
      },
      {
        "address": "[2620:fe::fe]:53",
        "weight": null, "state": "healthy",
        "queries": 36, "failures": 0,
        "timeouts": 0, "servfails": 0, "net_errors": 0,
        "consecutive_failures": 0,
        "last_failure_ago_s": null, "last_error": null
      }
    ]
  },
  "events": {
    "total_connections": 18963,
    "connection_errors": 12,
    "access_denied": 0,
    "blocked_domains": 0,
    "dns_no_ipv6": 4,
    "firewall_blocks": 0
  },
  "license": {
    "expires_at_unix": 1770484105,
    "days_left": 29,
    "is_active": true,
    "servers": {
      "L1": "online",
      "L2": "online"
    }
  },
  "telemetry": {
    "cpu_cores": 2,
    "total_mem_mb": 2048,
    "latest_cpu_usage": 4.8,
    "latest_mem_mb": 96
  },
  "server_ip": "1.2.3.4",
  "shaper": {
    "enabled": false,
    "rate_bytes": 0,
    "burst_bytes": 0
  }
}

Key fields:

Field Description
mitm Active and cumulative connections through MITM ports since startup
dns Cache hit and miss counts, how often the parallel query to a backup was used, and a line per server: its state, weight, how many queries it served and how its failures break down into timeouts, SERVFAILs and network errors. A server that stopped answering shows up here first
events.dns_no_ipv6 / firewall_blocks Domains without an AAAA record, and connections refused by the IP whitelist — the same categories as the dashboard chart in section 7.3
license.is_active Whether the licence is currently confirmed. When false, the proxy ports stay closed until the next check
telemetry Server CPU and RAM usage — the data behind the hardware panel in section 7.1
server_ip The public_ip value from the configuration
shaper Current shaping limits and counters, see section 5.7
listeners / mitm_listeners A verbatim echo of the matching config.yaml sections, handy for scripts that need the list of active ports and profiles
NoteStatistics are available without a token from localhost (127.0.0.1), so monitoring scripts running on the server itself need no credentials.

7. Web dashboard

The built-in dashboard is available at:

http://YOUR_IP:8080/dashboard?token=YOUR_TOKEN

7.1. Live monitoring

The dashboard lives at http://YOUR_IP:PORT/dashboard?token=YOUR_TOKEN, where PORT is the configured api_port. HTTPS is supported too, via api_port_https.

It refreshes every 10 seconds and shows:
- Hardware — CPU load, with the core count, and RAM usage, both with progress bars
- Network traffic — total ingress and egress in readable units, plus total and active TCP/UDP connection counts
- Licence and status — days remaining and the live online/offline state of each licence server
- Version and uptime — in the header

7.2. Traffic charts

Two throughput charts (Rx/Tx in Mbit/s) with average labels:
- Hourly — the last 60 minutes, one point per minute
- Daily — the last 24 hours, one point per hour

7.3. Connection Analytics

The doughnut chart breaks all connections down by category:

Category Colour Description
Success green Successfully proxied connections
Auth Denied yellow Refused because authentication failed
Conn Errors purple Network errors while establishing the connection
Blocked (DPI) grey Blocked by the domain blacklist
No IPv6 blue Domains with no AAAA record, that is, no IPv6
Firewall Blocks red Refused by the IP whitelist

7.4. IP whitelist management

The IP Whitelist panel manages allowed addresses and subnets straight from the browser, without restarting the service:
- View — lists every entry, with a lock icon marking system entries that cannot be removed
- Add — the input accepts a single address or a CIDR subnet such as 192.168.1.0/24. Press + Add Entry or Enter
- Remove — the button next to each entry. Removing 0.0.0.0/0 asks for confirmation, to avoid locking yourself out
- Import — the Import button loads a .txt file of addresses or CIDRs, one per line, with # comments supported

The list refreshes every 10 seconds, so changes made from another device or by another administrator appear without reloading the page.

CautionThe 0.0.0.0/0 entry allows connections from every address. Remove it and only the addresses explicitly listed will reach the proxy — make sure your own is among them first.

7.5. Recent Blocks

The Recent Blocks panel shows the last blocked connections, up to ten, with the address and the time. The Total counter gives the number of blocks since the service last started.

At the top of the dashboard, quick-copy buttons are generated per OS profile: Linux, Android, Windows, iOS and macOS. The SOCKS5 and HTTP buttons are disabled when that protocol is not enabled for the profile.

Clicking a button copies the credential-request URL (GET /allocate?port=...&mode=...) to the clipboard and shows a toast in the corner.

Below them, the TXT SOCKS5 and TXT HTTP buttons download the account file for that profile and mode directly. A button is disabled when the mode is not enabled for the profile, or the account file does not exist yet.

MITM listeners get their own card, holding the connection link and a Download CA certificate button. The client installs that CA once, after which all HTTPS traffic goes out under the selected browser profile.

7.8. Downloading account files

The Downloads section offers the account files for download, grouped by OS profile and proxy mode:

File Contents
accounts_1080_linux_socks5.txt SOCKS5 accounts for the Linux profile, port 1080
accounts_1081_android_socks5.txt SOCKS5 accounts for the Android profile
accounts_1081_android_http.txt HTTP accounts for the Android profile in hybrid mode
accounts_1082_windows_http.txt HTTP accounts for the Windows profile

Each file holds lines of the form protocol://login:password@IP:PORT, ready to import anywhere.

TipWhich files exist depends on the listeners and accounts_file settings. Hybrid listeners produce two files, SOCKS5 and HTTP.

7.7. Themes

The dashboard offers eight themes, switchable without reloading. The choice is remembered in the browser:

Theme Description
OxidProxy Dark The brand dark theme, used by default
Light Classic Classic light
Dracula Dark, purple and pink
Deep Ocean Deep navy
Teal Lagoon Dark teal
Gruvbox Retro Warm retro palette
Baroque Bling 💰 Baroque, with gold accents
Hacker Monochrome green on black

8. Service management

OxidProxy installs as a systemd service and runs as the oxidproxy user.

# start
systemctl start oxidproxy

# stop, gracefully - waits for active sessions to finish
systemctl stop oxidproxy

# restart
systemctl restart oxidproxy

# status
systemctl status oxidproxy

# enable at boot
systemctl enable oxidproxy

# follow the logs
journalctl -u oxidproxy -f
CautionDo not run OxidProxy directly as root. Doing so leaves the log and data files owned by root, which then causes permission errors when systemd starts the service as its own user. Always start it with systemctl start oxidproxy: systemd switches to the oxidproxy user declared in the unit file.

9. Logging and monitoring

Log files

File Description
/var/log/oxidproxy/oxidproxy.log Main log, at the verbosity set in the config
/var/log/oxidproxy/error.log Errors only

Log rotation

Logs are rotated automatically by logrotate:
- Daily, or once a file reaches 100 MB
- The last 10 generations are kept
- Compressed with gzip

System telemetry

Every 10 seconds a [SYS_STATS] line is written to the log:

[SYS_STATS] System Mem: 524/2048 MB | App Mem: 85 MB | CPU: 12.3% | Conns: 42 / 4096

10. Command line (CLI)

oxidproxy [OPTIONS]

Options:
  -c, --config <PATH>      Path to the configuration file (default: config.yaml)
  -t, --test [<PATH>]      Validate the configuration syntax
  -g, --generate           Write a sample config.yaml.example
  -b, --blacklist          Write a sample blacklist.txt.example
  -H, --hwid               Show the server HWID
  -p, --ping <HOST:PORT>   Check that a licence server is reachable
  -V, --version            Show the version
  -h, --help               Show this help

Examples:

# run with the default config
oxidproxy

# run with a specific config
oxidproxy -c /etc/oxidproxy/config.yaml

# validate the config before deploying
oxidproxy -t /etc/oxidproxy/config.yaml

# generate a sample configuration
oxidproxy -g

# check that a licence server is reachable
oxidproxy --ping address.given.by.support:8000

# show the HWID
oxidproxy -H

11. Troubleshooting

The service will not start

  1. Validate the configuration:
    oxidproxy -t /etc/oxidproxy/config.yaml

  2. Check the logs:
    journalctl -u oxidproxy --no-pager -n 50

  3. Check the licence server:
    oxidproxy --ping <HOST:PORT>
    Use an address given to you by support. The regular endpoints are built into the server and need no manual checking.

No connection through the proxy

  1. Make sure the client speaks a supported protocol: SOCKS5, SOCKS5h or HTTP CONNECT. SOCKS5h is recommended for maximum anonymity, as DNS is then resolved on the server.
  2. Check IPv6 routing — inspect /etc/rc.local and the output of:
    ip -6 route show
  3. Confirm the port is reachable from outside:
    ss -tlnp | grep oxidproxy
  4. Check the firewall (iptables or nftables)

Some sites do not open

OxidProxy works over IPv6 only. A target site without an AAAA record simply cannot be reached.

To check for an AAAA record:

dig AAAA example.com

The IP does not change

OxidProxy uses sticky sessions: the IP is bound to a login and password pair. To change it:
- Request new credentials via GET /allocate
- Or wait for rotation_interval to elapse and reconnect


12. FAQ

Q: What is SOCKS5h, and how does it differ from SOCKS5?

A: With SOCKS5h, DNS queries are resolved on the proxy server. Plain SOCKS5 resolves them on the client, which can leak DNS traffic and expose the real address. Always prefer SOCKS5h.


Q: Why are new logins and passwords generated on every restart?

A: By default accounts derive from a random seed. Uncomment and set account_seed in the config and the credentials will stay the same across restarts.


Q: Can I use several IPv6 subnets?

A: Yes. Add them to ipv6_subnets with different weights, and traffic is distributed in proportion.


Q: How do I find my server HWID?

A: Run oxidproxy -H. The HWID binds the licence to the machine.


Q: How much does OxidProxy consume?

A: With 100,000 accounts and around 50 active connections, roughly 80–120 MB of RAM and about 5% of one CPU core. Being written in Rust gives it high throughput and predictable memory use.


Q: Is the API secure?

A: With api_port_https enabled the API is served over HTTPS. Access is protected by master_token. Statistics at /stats are reachable without a token only from localhost.


Q: What is HTTP CONNECT mode?

A: HTTP CONNECT is the standard way to proxy HTTPS. The client sends CONNECT host:443 HTTP/1.1 with a Proxy-Authorization: Basic header, and an encrypted tunnel is established. Every browser supports it, as do curl, system proxy settings and most software.

Example with curl:

curl -x http://user_xxx:pass_xxx@YOUR_IP:1081 https://ifconfig.me

Q: How does hybrid differ from separate socks and http ports?

A: In hybrid mode one port accepts both. The protocol is detected from the first byte of the connection (0x05 means SOCKS5, anything else HTTP). It saves opening extra ports, and every feature — p0f, shaping, DNS, limits — behaves identically for both.


Q: What does the [mode] macro do in accounts_file?

A: On export, [mode] is replaced by the protocol, either socks5 or http. Hybrid listeners produce two files: one with socks5:// links and one with http://. For example accounts_1081_android_socks5.txt and accounts_1081_android_http.txt.


Q: The browser reports a certificate error on a MITM port.

A: A MITM port terminates TLS with its own certificate authority, so the client device must add the server CA to its trust store once; otherwise the browser treats the connection as insecure. The certificate is available from the /ca endpoint, or via the download button on the MITM card in the dashboard, described in section 7.6.


Q: What happens if the client User-Agent matches none of the mitm_listeners profiles?

A: By default the server falls back to the profile named in default. Set strict: true and it will refuse the connection instead.


13. Changelog

v2.4.1 — September 2026

v2.4.0 — September 2026

v2.3.7 — September 2026

v2.3.6 — September 2026

v2.2.0 — September 2026

v2.1.2 — August 2026

v2.1.0 — August 2026

v2.0.0 — June 2026

v1.8.1 — May 2026

v1.7.1 — April 2026

v1.7.0 — March 2026

v1.6.0 — January 2026