IP-based middleware rules (OIDC bypass, CIDR allowlist) seem ineffective #97

Closed
opened 2025-12-29 14:24:51 +01:00 by adam · 8 comments
Owner

Originally created by @deandre on GitHub (Aug 27, 2025).

Problem Summary

When running GoDoxy in Docker Compose (Orbstack) on macOS, all requests (both local and external) show RemoteAddr as 127.0.0.1, making all IP-based middleware rules ineffective for security purposes. This affects OIDC bypass rules, CIDR allowlists, and any other middleware that relies on client IP detection. This occurs whether Cloudflare proxy is enabled or disabled.

Environment Details

  • Platform: macOS (Mac mini)
  • Container Runtime: Docker Compose via Orbstack
  • Network Mode: network_mode: host
  • GoDoxy Version: v0.17.1
  • DNS/Proxy: Cloudflare with wildcard A record pointing to public IP (not Tunnels)

Steps to Reproduce

  1. Setup: Configure GoDoxy in Docker Compose with network_mode: host
  2. Test OIDC Bypass: Add bypass rules like remote 127.0.0.1 | remote 10.0.0.0/24
  3. Test CIDR Allowlist: Configure allowlist like allow: 127.0.0.1, 10.0.0.0/24
  4. Test 1: Cloudflare proxy enabled
  5. Test 2: Cloudflare proxy disabled (DNS only)
  6. Result: Both configurations show RemoteAddr: 127.0.0.1 in access log and external users bypass all IP-based restrictions

Expected Behavior

  • Local network requests should bypass OIDC/allowlist restrictions
  • External network requests should be blocked by CIDR allowlists
  • External network requests should require OIDC authentication

Actual Behavior

  • All requests show RemoteAddr: 127.0.0.1 in access logs
  • OIDC bypass: Rule remote 127.0.0.1 matches everyone
  • CIDR allowlist: Rule 127.0.0.1 matches everyone
  • External users can access services without authentication or IP restrictions

Evidence

Access Log Example

{
  "level": "info",
  "time": "27/Aug/2025:15:42:47 +0200",
  "ip": "127.0.0.1", 👈🏾
  "method": "GET",
  "scheme": "https",
  "host": "[host.example.com]",
  "path": "/api/siteMonitor",
  "protocol": "HTTP/2.0",
  "status": 200,
  "type": "application/json; charset=utf-8",
  "size": 42,
  "referer": "[host.example.com]",
  "useragent": "[user agent]",
  "query": {
    "groupName": [
      "Home"
    ],
    "serviceName": [
      "Homebridge"
    ]
  },
  "headers": {
    "X-Forwarded-For": [
      "[public IPv6 address]"
    ]
  },
  "cookies": {}
}

config.yaml


  middlewares:
    - use: CloudflareRealIP
    - use: ModifyResponse
      set_headers:
        Access-Control-Allow-Methods: GET, POST, PUT, PATCH, DELETE, OPTIONS, HEAD
        Access-Control-Allow-Headers: "*"
        Access-Control-Allow-Origin: "*"
        Access-Control-Max-Age: 86400
        Vary: "*"
        X-XSS-Protection: 1; mode=block
        Content-Security-Policy: "object-src 'self'; frame-ancestors 'self';"
        X-Content-Type-Options: nosniff
        X-Frame-Options: SAMEORIGIN
        Referrer-Policy: same-origin
        Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
    # - use: CIDRWhitelist
    #   allow:
    #     - "127.0.0.1"
    #     - "10.0.0.0/8"
    #     - "172.16.0.0/12"
    #     - "192.168.0.0/16"
    #   status: 403
    #   message: "Forbidden"
    # - use: RedirectHTTP

  # below enables access log
  access_log:
    format: json
    path: /app/logs/access.log
    stdout: true
    fields:
      headers:
        default: drop
        config:
          X-Real-IP: keep
          CF-Connecting-IP: keep
          X-Forwarded-For: keep

Affected Middleware Examples

OIDC Bypass

# homepage/compose.yaml
proxy.#1.middlewares.oidc.bypass: remote 127.0.0.1 | remote 10.0.0.0/24 | remote 192.168.0.0/16 | remote 100.64.0.0/10 | remote ::1 | remote [public IPv6]

CIDR Allowlist

# config.yml
entrypoint:
  middlewares:
    - use: CIDRWhitelist
      allow:
        - "127.0.0.1"
        - "10.0.0.0/24"
        - "192.168.0.0/16"
      status: 403
      message: "Forbidden"

I may have misconfigured some thing, but I'm curious if anyone else has run into this?

Originally created by @deandre on GitHub (Aug 27, 2025). ## Problem Summary When running GoDoxy in Docker Compose (Orbstack) on macOS, all requests (both local and external) show `RemoteAddr` as `127.0.0.1`, making **all IP-based middleware rules ineffective** for security purposes. This affects OIDC bypass rules, CIDR allowlists, and any other middleware that relies on client IP detection. This occurs whether Cloudflare proxy is enabled or disabled. ## Environment Details - **Platform**: macOS (Mac mini) - **Container Runtime**: Docker Compose via Orbstack - **Network Mode**: `network_mode: host` - **GoDoxy Version**: v0.17.1 - **DNS/Proxy**: Cloudflare with wildcard A record pointing to public IP (not Tunnels) ## Steps to Reproduce 1. **Setup**: Configure GoDoxy in Docker Compose with `network_mode: host` 2. **Test OIDC Bypass**: Add bypass rules like `remote 127.0.0.1 | remote 10.0.0.0/24` 3. **Test CIDR Allowlist**: Configure allowlist like `allow: 127.0.0.1, 10.0.0.0/24` 4. **Test 1**: Cloudflare proxy enabled 5. **Test 2**: Cloudflare proxy disabled (DNS only) 6. **Result**: Both configurations show `RemoteAddr: 127.0.0.1` in access log and external users bypass all IP-based restrictions ## Expected Behavior - Local network requests should bypass OIDC/allowlist restrictions - External network requests should be blocked by CIDR allowlists - External network requests should require OIDC authentication ## Actual Behavior - All requests show `RemoteAddr: 127.0.0.1` in access logs - **OIDC bypass**: Rule `remote 127.0.0.1` matches everyone - **CIDR allowlist**: Rule `127.0.0.1` matches everyone - External users can access services without authentication or IP restrictions ## Evidence ### Access Log Example ```json { "level": "info", "time": "27/Aug/2025:15:42:47 +0200", "ip": "127.0.0.1", 👈🏾 "method": "GET", "scheme": "https", "host": "[host.example.com]", "path": "/api/siteMonitor", "protocol": "HTTP/2.0", "status": 200, "type": "application/json; charset=utf-8", "size": 42, "referer": "[host.example.com]", "useragent": "[user agent]", "query": { "groupName": [ "Home" ], "serviceName": [ "Homebridge" ] }, "headers": { "X-Forwarded-For": [ "[public IPv6 address]" ] }, "cookies": {} } ``` ### config.yaml ```yaml middlewares: - use: CloudflareRealIP - use: ModifyResponse set_headers: Access-Control-Allow-Methods: GET, POST, PUT, PATCH, DELETE, OPTIONS, HEAD Access-Control-Allow-Headers: "*" Access-Control-Allow-Origin: "*" Access-Control-Max-Age: 86400 Vary: "*" X-XSS-Protection: 1; mode=block Content-Security-Policy: "object-src 'self'; frame-ancestors 'self';" X-Content-Type-Options: nosniff X-Frame-Options: SAMEORIGIN Referrer-Policy: same-origin Strict-Transport-Security: max-age=63072000; includeSubDomains; preload # - use: CIDRWhitelist # allow: # - "127.0.0.1" # - "10.0.0.0/8" # - "172.16.0.0/12" # - "192.168.0.0/16" # status: 403 # message: "Forbidden" # - use: RedirectHTTP # below enables access log access_log: format: json path: /app/logs/access.log stdout: true fields: headers: default: drop config: X-Real-IP: keep CF-Connecting-IP: keep X-Forwarded-For: keep ``` ### Affected Middleware Examples #### OIDC Bypass ```yaml # homepage/compose.yaml proxy.#1.middlewares.oidc.bypass: remote 127.0.0.1 | remote 10.0.0.0/24 | remote 192.168.0.0/16 | remote 100.64.0.0/10 | remote ::1 | remote [public IPv6] ``` #### CIDR Allowlist ```yaml # config.yml entrypoint: middlewares: - use: CIDRWhitelist allow: - "127.0.0.1" - "10.0.0.0/24" - "192.168.0.0/16" status: 403 message: "Forbidden" ``` I may have misconfigured some thing, but I'm curious if anyone else has run into this?
adam closed this issue 2025-12-29 14:24:51 +01:00
Author
Owner

@yusing commented on GitHub (Aug 27, 2025):

Wow! Thanks for detailed testing like this. Will check it tmr it's already midnight here.

@yusing commented on GitHub (Aug 27, 2025): Wow! Thanks for detailed testing like this. Will check it tmr it's already midnight here.
Author
Owner

@yusing commented on GitHub (Aug 28, 2025):

Hi, I have just done some checking.

  • The access log of mine and IPs logged is not 127.0.0.1
  • The only code that modifies (*http.Request).RemoteAddr is the RealIP middleware (and CloudflareRealIP which derives from RealIP).

In your case:

  • CloudflareRealIP is used, but it will do nothing since CF-Connecting-IP is not present (since you're doing neither tunnel nor cf proxy).
  • The RemoteAddr value was definitely legit.

Few more questions:

  • Have you tried connecting to GoDoxy with other devices (not the one running the server), on the other network (e.g. Cellular Data). Could you see non 127.0.0.1 ips from the logs?
  • Do you have anything put in front of GoDoxy? (e.g. WAF, loadbalancer, etc.)
@yusing commented on GitHub (Aug 28, 2025): Hi, I have just done some checking. - The access log of mine and IPs logged is not `127.0.0.1` - The only code that modifies (*http.Request).RemoteAddr is the RealIP middleware (and CloudflareRealIP which derives from RealIP). In your case: - CloudflareRealIP is used, but it will do nothing since `CF-Connecting-IP` is not present (since you're doing neither tunnel nor cf proxy). - The RemoteAddr value was definitely legit. Few more questions: - Have you tried connecting to GoDoxy with other devices (not the one running the server), on the other network (e.g. Cellular Data). Could you see non `127.0.0.1` ips from the logs? - Do you have anything put in front of GoDoxy? (e.g. WAF, loadbalancer, etc.)
Author
Owner

@deandre commented on GitHub (Aug 28, 2025):

On my mobile device, disconnected from VPN and WiFi, I see the same.

{
  "level": "info",
  "time": "28/Aug/2025:06:33:45 +0200",
  "ip": "127.0.0.1",
  "method": "GET",
  "scheme": "https",
  "host": "go.[DOMAIN]",
  "path": "/api/services/proxy",
  "protocol": "HTTP/2.0",
  "status": 200,
  "type": "application/json;charset=UTF-8",
  "size": 5477,
  "referer": "https://go.[DOMAIN]",
  "useragent": "[redacted]",
  "query": {
    "endpoint": [
      "get_activity"
    ],
    "query": [
      "{\"refreshInterval\":5000}"
    ],
    "group": [
      "Monitor"
    ],
    "service": [
      "Tautulli"
    ],
    "index": [
      "0"
    ]
  },
  "headers": {
    "X-Forwarded-For": [
      "41.[redacted public IP]"
    ]
  },
  "cookies": {}
}

I noticed CF-Connecting-IP was being dropped from logs, despite keeping it in my access log config.

  access_log:
    format: json
    path: /app/logs/access.log
    stdout: true
    fields:
      headers:
        default: drop
        config:
          X-Real-IP: keep
          CF-Connecting-IP: keep
          X-Forwarded-For: keep

I added the following to my middleware config, and then saw CF-Connecting-IP being written to logs, but the IP didn't change (it's still localhost, and I did switch back to WiFi here).

     - use: request
      set_headers:
        CF-Connecting-IP: $header(X-Forwarded-For)
{
  "level": "info",
  "time": "28/Aug/2025:07:06:40 +0200",
  "ip": "127.0.0.1",
  "method": "GET",
  "scheme": "https",
  "host": "logs.[DOMAIN]",
  "path": "/assets/main-KuuBQbdR.css",
  "protocol": "HTTP/2.0",
  "status": 200,
  "type": "text/css; charset=utf-8",
  "size": 21824,
  "referer": "https://logs.[DOMAIN]",
  "useragent": "[redacted]",
  "query": {},
  "headers": {
    "X-Forwarded-For": [
      "2c0f:[redacted public IPv6]"
    ],
    "CF-Connecting-IP": [
      "2c0f:[redacted public IPv6]"
    ]
  },
  "cookies": {}
}

This occurs whether or not the DNS record is proxied (it is proxied, however).

Image

I've got nothing in front of GoDoxy. 🤔 Thank you for looking into this!

@deandre commented on GitHub (Aug 28, 2025): On my mobile device, disconnected from VPN and WiFi, I see the same. ```yaml { "level": "info", "time": "28/Aug/2025:06:33:45 +0200", "ip": "127.0.0.1", "method": "GET", "scheme": "https", "host": "go.[DOMAIN]", "path": "/api/services/proxy", "protocol": "HTTP/2.0", "status": 200, "type": "application/json;charset=UTF-8", "size": 5477, "referer": "https://go.[DOMAIN]", "useragent": "[redacted]", "query": { "endpoint": [ "get_activity" ], "query": [ "{\"refreshInterval\":5000}" ], "group": [ "Monitor" ], "service": [ "Tautulli" ], "index": [ "0" ] }, "headers": { "X-Forwarded-For": [ "41.[redacted public IP]" ] }, "cookies": {} } ``` I noticed `CF-Connecting-IP` was being dropped from logs, despite keeping it in my access log config. ```yaml access_log: format: json path: /app/logs/access.log stdout: true fields: headers: default: drop config: X-Real-IP: keep CF-Connecting-IP: keep X-Forwarded-For: keep ``` I added the following to my middleware config, and then saw `CF-Connecting-IP` being written to logs, but the IP didn't change (it's still localhost, and I did switch back to WiFi here). ```yaml - use: request set_headers: CF-Connecting-IP: $header(X-Forwarded-For) ``` ```yaml { "level": "info", "time": "28/Aug/2025:07:06:40 +0200", "ip": "127.0.0.1", "method": "GET", "scheme": "https", "host": "logs.[DOMAIN]", "path": "/assets/main-KuuBQbdR.css", "protocol": "HTTP/2.0", "status": 200, "type": "text/css; charset=utf-8", "size": 21824, "referer": "https://logs.[DOMAIN]", "useragent": "[redacted]", "query": {}, "headers": { "X-Forwarded-For": [ "2c0f:[redacted public IPv6]" ], "CF-Connecting-IP": [ "2c0f:[redacted public IPv6]" ] }, "cookies": {} } ``` This occurs whether or not the DNS record is proxied (it is proxied, however). <img width="2320" height="236" alt="Image" src="https://github.com/user-attachments/assets/f3327a08-48ba-4b2e-8a5d-83eea7de18e5" /> I've got nothing in front of GoDoxy. 🤔 Thank you for looking into this!
Author
Owner

@yusing commented on GitHub (Aug 28, 2025):

Ah I missed the point that you're running on macOS...

I don't run docker on macOS, but these are my thoughts:

macOS Docker’s host networking isn’t a true Linux host network. Even if docker doesn't complain about it, macOS does not support host network.

The connection flow would be something like:

User -> macOS -> docker as a middleman -> godoxy

GoDoxy can only see 127.0.0.1 as a result.

You may verify that by running traefik/whoami in host network mode on your mac and open it in browser.

@yusing commented on GitHub (Aug 28, 2025): Ah I missed the point that you're running on macOS... I don't run docker on macOS, but these are my thoughts: macOS Docker’s host networking isn’t a true Linux `host` network. Even if docker doesn't complain about it, macOS does not support `host` network. The connection flow would be something like: User -> macOS -> docker as a middleman -> godoxy GoDoxy can only see 127.0.0.1 as a result. You may verify that by running `traefik/whoami` in host network mode on your mac and open it in browser.
Author
Owner

@yusing commented on GitHub (Aug 28, 2025):

CF-Connecting-IP will only be available when you use cf proxy or tunnel. If you have visited your sites before when proxy was off, after turning back on you're still likely having direct connections because of DNS caching.

@yusing commented on GitHub (Aug 28, 2025): `CF-Connecting-IP` will only be available when you use cf proxy or tunnel. If you have visited your sites before when proxy was off, after turning back on you're still likely having direct connections because of DNS caching.
Author
Owner

@deandre commented on GitHub (Aug 28, 2025):

Indeed the problem is with Orbstack. https://github.com/orbstack/orbstack/issues/710 😅 Sorry for the noise, but thanks again for taking a look!

@deandre commented on GitHub (Aug 28, 2025): Indeed the problem is with Orbstack. https://github.com/orbstack/orbstack/issues/710 😅 Sorry for the noise, but thanks again for taking a look!
Author
Owner

@yusing commented on GitHub (Aug 28, 2025):

No problem! Let me know if you have any questions. If you need to use those security features without problem, you may build it and run the binary.

@yusing commented on GitHub (Aug 28, 2025): No problem! Let me know if you have any questions. If you need to use those security features without problem, you may build it and run the binary.
Author
Owner

@deandre commented on GitHub (Aug 28, 2025):

Two steps ahead of ya — thanks again! 😅

@deandre commented on GitHub (Aug 28, 2025): Two steps ahead of ya — thanks again! 😅
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/godoxy-yusing#97