[Bug] Cannot Ban Specific Derp Region using RegionID #957

Closed
opened 2025-12-29 02:26:42 +01:00 by adam · 4 comments
Owner

Originally created by @panteparak on GitHub (Feb 25, 2025).

Is this a support request?

  • This is not a support request

Is there an existing issue for this?

  • I have searched the existing issues

Current Behavior

Currently, there are no ways to exclude some region from the tailscale default derp map from within headscale server.
It is a non or all through the

Expected Behavior

Expected to be able to exclude some region from the predefine derpmap.

Within Tailscale Official Document. It should be achievable like so.

{
  // ... other parts of tailnet policy file
  "derpMap": { "Regions": { "1": null } }
}

Docs: https://tailscale.com/kb/1118/custom-derp-servers#optional-remove-tailscales-derp-servers

Steps To Reproduce

Using the derp config similar to my set up below.
Run tailscale netcheck to view the nearest available derp nodes

Environment

- OS: Ubuntu 24.04
- Headscale version: 0.24.2
- Tailscale version: 1.80.2 (Mac OSX)

Runtime environment

  • Headscale is behind a (reverse) proxy
  • Headscale runs in a container

Anything else?

Headscale Config Snippet

derp:
      server:
        enabled: false
        region_id: 999
        region_code: "headscale"
        region_name: "Headscale Embedded DERP"
        stun_listen_addr: "0.0.0.0:3478"
        private_key_path: /var/lib/headscale/derp_server_private.key

        automatically_add_embedded_derp_region: true
        ipv4: 1.2.3.4
        ipv6: 2001:db8::1
      urls:
        - https://controlplane.tailscale.com/derpmap/default
      paths:
        - /etc/tailscale-derp/custom-tailscale-derp-region.yaml
      auto_update_enabled: true
      update_frequency: 1h

custom-tailscale-derp-region.yaml

regions:
  3: {} # null does not work also
  6: {}
  20: {}
  900:
    regionid: 900
    regioncode: sgp1
    regionname: <REDACTED>
    nodes:
      - name: <REDACTED>
        regionid: 900
        hostname: <REDACTED>
        ipv4: <REDACTED>
        ipv6: ""
        stunport: 0
        stunonly: false
        derpport: 0

Tailscale Netcheck

Report:
	* Time: 2025-02-25T10:50:08.798843Z
	* UDP: true
	* IPv4: yes, <REDACTED>:42073
	* IPv6: no, but OS has support
	* MappingVariesByDestIP: true
	* PortMapping: UPnP, NAT-PMP, PCP
	* CaptivePortal: false
	* Nearest DERP: Singapore
	* DERP latency:
		- sin: 38.2ms  (Singapore)
		- sgp1: 38.3ms  (Digital Ocean SGP1)

At the time of writing this. Default Tailscale DerpMap
RegionID 3, is referring to Singapore (SIN)

{
  "Regions": {
    "3": {
      "RegionID": 3,
      "RegionCode": "sin",
      "RegionName": "Singapore",
      "Latitude": 1.3521,
      "Longitude": 103.8198,
      "Nodes": [
        {
          "Name": "3b",
          "RegionID": 3,
          "HostName": "derp3b.tailscale.com",
          "IPv4": "43.245.49.105",
          "IPv6": "2403:2500:300::b0c",
          "CanPort80": true
        },
        {
          "Name": "3c",
          "RegionID": 3,
          "HostName": "derp3c.tailscale.com",
          "IPv4": "43.245.49.83",
          "IPv6": "2403:2500:300::57a",
          "CanPort80": true
        },
        {
          "Name": "3d",
          "RegionID": 3,
          "HostName": "derp3d.tailscale.com",
          "IPv4": "43.245.49.144",
          "IPv6": "2403:2500:300::df9",
          "CanPort80": true
        }
      ]
    }
  }
}
Originally created by @panteparak on GitHub (Feb 25, 2025). ### Is this a support request? - [x] This is not a support request ### Is there an existing issue for this? - [x] I have searched the existing issues ### Current Behavior Currently, there are no ways to exclude some region from the tailscale default derp map from within headscale server. It is a non or all through the ### Expected Behavior Expected to be able to exclude some region from the predefine derpmap. Within Tailscale Official Document. It should be achievable like so. ``` { // ... other parts of tailnet policy file "derpMap": { "Regions": { "1": null } } } ``` Docs: https://tailscale.com/kb/1118/custom-derp-servers#optional-remove-tailscales-derp-servers ### Steps To Reproduce Using the derp config similar to my set up below. Run `tailscale netcheck` to view the nearest available derp nodes ### Environment ```markdown - OS: Ubuntu 24.04 - Headscale version: 0.24.2 - Tailscale version: 1.80.2 (Mac OSX) ``` ### Runtime environment - [x] Headscale is behind a (reverse) proxy - [x] Headscale runs in a container ### Anything else? Headscale Config Snippet ``` derp: server: enabled: false region_id: 999 region_code: "headscale" region_name: "Headscale Embedded DERP" stun_listen_addr: "0.0.0.0:3478" private_key_path: /var/lib/headscale/derp_server_private.key automatically_add_embedded_derp_region: true ipv4: 1.2.3.4 ipv6: 2001:db8::1 urls: - https://controlplane.tailscale.com/derpmap/default paths: - /etc/tailscale-derp/custom-tailscale-derp-region.yaml auto_update_enabled: true update_frequency: 1h ``` `custom-tailscale-derp-region.yaml` ``` regions: 3: {} # null does not work also 6: {} 20: {} 900: regionid: 900 regioncode: sgp1 regionname: <REDACTED> nodes: - name: <REDACTED> regionid: 900 hostname: <REDACTED> ipv4: <REDACTED> ipv6: "" stunport: 0 stunonly: false derpport: 0 ``` Tailscale Netcheck ``` Report: * Time: 2025-02-25T10:50:08.798843Z * UDP: true * IPv4: yes, <REDACTED>:42073 * IPv6: no, but OS has support * MappingVariesByDestIP: true * PortMapping: UPnP, NAT-PMP, PCP * CaptivePortal: false * Nearest DERP: Singapore * DERP latency: - sin: 38.2ms (Singapore) - sgp1: 38.3ms (Digital Ocean SGP1) ``` At the time of writing this. Default Tailscale [DerpMap](https://controlplane.tailscale.com/derpmap/default) RegionID 3, is referring to Singapore (SIN) ``` { "Regions": { "3": { "RegionID": 3, "RegionCode": "sin", "RegionName": "Singapore", "Latitude": 1.3521, "Longitude": 103.8198, "Nodes": [ { "Name": "3b", "RegionID": 3, "HostName": "derp3b.tailscale.com", "IPv4": "43.245.49.105", "IPv6": "2403:2500:300::b0c", "CanPort80": true }, { "Name": "3c", "RegionID": 3, "HostName": "derp3c.tailscale.com", "IPv4": "43.245.49.83", "IPv6": "2403:2500:300::57a", "CanPort80": true }, { "Name": "3d", "RegionID": 3, "HostName": "derp3d.tailscale.com", "IPv4": "43.245.49.144", "IPv6": "2403:2500:300::df9", "CanPort80": true } ] } } } ```
adam added the bughelp wantedDERP labels 2025-12-29 02:26:42 +01:00
adam closed this issue 2025-12-29 02:26:42 +01:00
Author
Owner

@yangboyd commented on GitHub (Feb 28, 2025):

Does the OmitDefaultRegions work?

@yangboyd commented on GitHub (Feb 28, 2025): Does the OmitDefaultRegions work?
Author
Owner

@panteparak commented on GitHub (Feb 28, 2025):

Does the OmitDefaultRegions work?

No, doesn't work. I figured it might be a letter casing issue so i try it with some combination of upper and lower cases.

OmitDefaultRegions: true
omitdefaultregions: true
omitDefaultRegions: true
regions:
  3: {}
  6: {}
  20: {}
  900:
    regionid: 900
    regioncode: sgp1
    regionname: Digital Ocean SGP1
    nodes:
      - name: <REDACTED>
        regionid: 900
        hostname: <REDACTED>
        ipv4: <REDACTED>
        ipv6: ""
        stunport: 0
        stunonly: false
        derpport: 0

But another workaround to achieve OmitDefaultRegions, is to set derp.url (Link) as empty list.

Just so we're not off-topic. The goal is, to BAN some derp region in a DERPMap

@panteparak commented on GitHub (Feb 28, 2025): > Does the OmitDefaultRegions work? No, doesn't work. I figured it might be a letter casing issue so i try it with some combination of upper and lower cases. ``` OmitDefaultRegions: true omitdefaultregions: true omitDefaultRegions: true regions: 3: {} 6: {} 20: {} 900: regionid: 900 regioncode: sgp1 regionname: Digital Ocean SGP1 nodes: - name: <REDACTED> regionid: 900 hostname: <REDACTED> ipv4: <REDACTED> ipv6: "" stunport: 0 stunonly: false derpport: 0 ``` But another workaround to achieve `OmitDefaultRegions`, is to set `derp.url` ([Link](https://github.com/juanfont/headscale/blob/main/config-example.yaml#L113-L114)) as empty list. Just so we're not off-topic. The goal is, to BAN some derp region in a DERPMap
Author
Owner

@hdhoang commented on GitHub (May 23, 2025):

From debug log, I think the applied ordering is paths... (yaml format with lowercase, numeric keys) -> urls[0] (ts' json format) -> embedded DERP (when enabled & configured to inject). And later entries overrides previous entries.

{"level":"debug","func":"GetDERPMap","path":"/..."
{"level":"debug","func":"GetDERPMap","path":"/..."
{"level":"debug","func":"GetDERPMap","url":"https://controlplane.tailscale.com/derpmap/default","time":....,"message":"Loading DERPMap from path"}
{"level":"info","caller":"/home/runner/work/headscale/headscale/hscontrol/derp/server/derp_server.go:106","time":1747725677,"message":"DERP region: {RegionID:999 RegionCode:...

So my workaround to nullify some TS' regions are:

  • have urls empty
  • download the json, convert to yaml with something like yq, lower-case the keys (or just all strings), and edit the regions subkeys to be integer literals
  • add that file as paths[0]
  • add this as paths[1]
regions:
  17: null

and my nodes don't see derp17 anymore.

We can work on a patch to change the ordering to make override easier.

@hdhoang commented on GitHub (May 23, 2025): From debug log, I think the applied ordering is `paths...` (yaml format with lowercase, numeric keys) -> `urls[0]` (ts' json format) -> embedded DERP (when enabled & configured to inject). And later entries overrides previous entries. ```json {"level":"debug","func":"GetDERPMap","path":"/..." {"level":"debug","func":"GetDERPMap","path":"/..." {"level":"debug","func":"GetDERPMap","url":"https://controlplane.tailscale.com/derpmap/default","time":....,"message":"Loading DERPMap from path"} {"level":"info","caller":"/home/runner/work/headscale/headscale/hscontrol/derp/server/derp_server.go:106","time":1747725677,"message":"DERP region: {RegionID:999 RegionCode:... ``` So my workaround to nullify some TS' regions are: - have `urls` empty - download the json, convert to yaml with something like `yq`, lower-case the keys (or just all strings), and edit the `regions` subkeys to be integer literals - add that file as `paths[0]` - add this as `paths[1]` ```yaml regions: 17: null ``` and my nodes don't see derp17 anymore. We can work on a patch to change the ordering to make override easier.
Author
Owner

@github-actions[bot] commented on GitHub (Aug 22, 2025):

This issue is stale because it has been open for 90 days with no activity.

@github-actions[bot] commented on GitHub (Aug 22, 2025): This issue is stale because it has been open for 90 days with no activity.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/headscale#957