# How S-UI Implements the Transparent Proxy Feature: A Code-Level Analysis

> Discover how S UI implements transparent proxy functionality. Dive into the code level analysis and understand its integration with the sing box engine for efficient packet interception.

- Repository: [Alireza Ahmadi/s-ui](https://github.com/alireza0/s-ui)
- Tags: deep-dive
- Published: 2026-05-22

---

**S-UI implements transparent proxy (tproxy) functionality by generating a JSON inbound configuration with `"type": "tproxy"` and delegating packet interception to the underlying sing-box engine, which binds to a specified port using Linux's `IP_TRANSPARENT` socket option.**

The **transparent proxy** feature in S-UI enables traffic interception at the network layer without requiring application-level proxy configuration. According to the `alireza0/s-ui` source code, this capability is not implemented natively within S-UI itself but rather orchestrated through a lightweight wrapper around the sing-box proxy engine.

## Architecture Overview

S-UI functions as a configuration management layer that prepares and validates JSON definitions before handing them to sing-box. When users enable transparent proxy mode, S-UI constructs an inbound definition that sing-box's `InboundRegistry` recognizes as a transparent proxy type. This design delegates the complex network-level packet interception to sing-box while S-UI handles the UI, storage, and lifecycle management.

## Step-by-Step Implementation Flow

### User Configuration and JSON Generation

The process begins when a user selects the **Transparent Proxy** option in the S-UI interface. In [`service/inbounds.go`](https://github.com/alireza0/s-ui/blob/main/service/inbounds.go), the `service.InboundService.Save` method unmarshals the submitted configuration into a `model.Inbound` struct from [`database/model/inbounds.go`](https://github.com/alireza0/s-ui/blob/main/database/model/inbounds.go). This struct holds the `Type`, `Tag`, and network parameters required for the tproxy configuration.

The service layer constructs a JSON object containing the mandatory fields sing-box expects:

```go
inbound := map[string]interface{}{
    "type":        "tproxy",
    "listen":      "0.0.0.0",
    "listen_port": 12345,
    "tag":         "transparent-in",
}

```

### Core Registration and InboundRegistry

After validation, the system checks if the sing-box core is active via `corePtr.IsRunning()`. If running, the code invokes `corePtr.AddInbound(inboundConfig)` to register the new inbound with the live engine.

The `core.NewCore()` function in [`core/main.go`](https://github.com/alireza0/s-ui/blob/main/core/main.go) initializes the global sing-box context using:

```go
globalCtx = sb.Context(globalCtx,
    InboundRegistry(), OutboundRegistry(),
    EndpointRegistry(), DNSTransportRegistry(),
    ServiceRegistry())

```

The `InboundRegistry()` defined in [`core/registry.go`](https://github.com/alireza0/s-ui/blob/main/core/registry.go) registers built-in inbound types that sing-box supports, including the `tproxy` type. When `AddInbound` processes the configuration, sing-box looks up the `"type": "tproxy"` entry in this registry to instantiate the appropriate listener.

### Traffic Interception at the Network Layer

Once registered, sing-box creates a transparent proxy listener that binds to the specified address and port. This listener utilizes Linux's `IP_TRANSPARENT` socket option to intercept traffic at the network layer while preserving the original client IP address. Incoming packets are then forwarded to the appropriate outbound based on user-defined routing rules without modifying the source address.

### Outbound JSON Short-Circuit

Unlike other inbound types that may require additional outbound processing, transparent proxies are handled specially in [`util/outJson.go`](https://github.com/alireza0/s-ui/blob/main/util/outJson.go). The `util.FillOutJson` function contains a switch statement that returns early for tproxy configurations:

```go
case "direct", "tun", "redirect", "tproxy":
    return nil

```

This optimization occurs because tproxy inbounds operate as pure traffic interceptors and do not require S-UI to generate complementary outbound JSON payloads. The core handles the entire forwarding logic internally once the inbound is established.

## Practical Implementation Example

To add a transparent proxy programmatically through S-UI's service layer:

```go
// Build the tproxy inbound configuration
inbound := map[string]interface{}{
    "type":        "tproxy",
    "listen":      "0.0.0.0",
    "listen_port": 12345,
    "tag":         "transparent-in",
}
inboundJSON, _ := json.Marshal(inbound)

// Add to the running sing-box core
if corePtr.IsRunning() {
    err := corePtr.AddInbound(inboundJSON)
    if err != nil {
        logger.Error("failed to add tproxy inbound:", err)
    }
}

// Skip outbound JSON processing (no-op for tproxy)
var inboundModel model.Inbound
_ = json.Unmarshal(inboundJSON, &inboundModel)
_ = util.FillOutJson(&inboundModel, "my.hostname.com")

```

## Key Source Files and Responsibilities

- **[`core/main.go`](https://github.com/alireza0/s-ui/blob/main/core/main.go)**: Bootstraps the sing-box context and initializes registries
- **[`core/registry.go`](https://github.com/alireza0/s-ui/blob/main/core/registry.go)**: Defines `InboundRegistry()` which registers the `tproxy` type with sing-box
- **[`service/inbounds.go`](https://github.com/alireza0/s-ui/blob/main/service/inbounds.go)**: Implements `InboundService.Save` for configuration validation and core communication
- **[`util/outJson.go`](https://github.com/alireza0/s-ui/blob/main/util/outJson.go)**: Contains the logic that skips unnecessary outbound processing for transparent proxies
- **[`database/model/inbounds.go`](https://github.com/alireza0/s-ui/blob/main/database/model/inbounds.go)**: Defines the data structures storing inbound configuration parameters

## Summary

- **S-UI delegates transparent proxy functionality** to sing-box's native `tproxy` inbound rather than implementing packet interception itself
- **Configuration flows through four layers**: UI → Service ([`service/inbounds.go`](https://github.com/alireza0/s-ui/blob/main/service/inbounds.go)) → Registry ([`core/registry.go`](https://github.com/alireza0/s-ui/blob/main/core/registry.go)) → sing-box Core
- **`util.FillOutJson` optimizes processing** by returning `nil` for tproxy types, eliminating unnecessary outbound JSON generation
- **Linux `IP_TRANSPARENT` enables true transparency** by preserving original client IP addresses during packet interception
- **The `InboundRegistry` pattern** allows S-UI to support sing-box's full range of inbound types through a unified registration mechanism

## Frequently Asked Questions

### What is the difference between redirect and transparent proxy in S-UI?

**Redirect mode** operates at the application layer and modifies packet destinations, while **transparent proxy (tproxy)** operates at the network layer using Linux's `IP_TRANSPARENT` socket option to intercept packets without altering headers. According to the source code in [`util/outJson.go`](https://github.com/alireza0/s-ui/blob/main/util/outJson.go), both types are treated similarly in terms of outbound JSON processing (both return `nil` in the switch case), but tproxy preserves the original source IP address whereas redirect does not.

### Why does S-UI rely on sing-box instead of implementing transparent proxy natively?

**S-UI functions specifically as a management interface** rather than a proxy engine. The [`core/main.go`](https://github.com/alireza0/s-ui/blob/main/core/main.go) implementation shows that S-UI initializes sing-box's global context and delegates all packet handling to the underlying engine. This architectural decision allows S-UI to leverage sing-box's mature networking stack, `IP_TRANSPARENT` socket handling, and performance optimizations while focusing the S-UI codebase on configuration management, user interface, and API endpoints.

### How does S-UI handle transparent proxy configuration when the core is offline?

**The service layer queues the configuration** during the save operation. In [`service/inbounds.go`](https://github.com/alireza0/s-ui/blob/main/service/inbounds.go), the `Save` method checks `corePtr.IsRunning()` before calling `AddInbound()`. If the core is not running, the JSON configuration is still persisted to the database through the `model.Inbound` struct. When the core subsequently starts via `NewCore()`, the existing configurations are loaded and registered with the `InboundRegistry`, activating the transparent proxy listeners at that time.

### What network privileges does S-UI require for transparent proxy to function?

**The sing-box process requires `CAP_NET_ADMIN` capability** or root privileges to create sockets with the `IP_TRANSPARENT` option. While S-UI itself runs as a management service, the actual binding and packet interception occur within the sing-box core process. The `AddInbound` call in the source code assumes the core process has sufficient privileges to bind to the specified port and set the necessary socket options for transparent interception.