| 19 | const DisableSTUN = "disable" |
| 20 | |
| 21 | func STUNRegions(baseRegionID int, stunAddrs []string) ([]*tailcfg.DERPRegion, error) { |
| 22 | regions := make([]*tailcfg.DERPRegion, 0, len(stunAddrs)) |
| 23 | for index, stunAddr := range stunAddrs { |
| 24 | if stunAddr == DisableSTUN { |
| 25 | return []*tailcfg.DERPRegion{}, nil |
| 26 | } |
| 27 | |
| 28 | host, rawPort, err := net.SplitHostPort(stunAddr) |
| 29 | if err != nil { |
| 30 | return nil, xerrors.Errorf("split host port for %q: %w", stunAddr, err) |
| 31 | } |
| 32 | port, err := strconv.Atoi(rawPort) |
| 33 | if err != nil { |
| 34 | return nil, xerrors.Errorf("parse port for %q: %w", stunAddr, err) |
| 35 | } |
| 36 | |
| 37 | regionID := baseRegionID + index + 1 |
| 38 | regions = append(regions, &tailcfg.DERPRegion{ |
| 39 | EmbeddedRelay: false, |
| 40 | RegionID: regionID, |
| 41 | RegionCode: fmt.Sprintf("coder_stun_%d", regionID), |
| 42 | RegionName: fmt.Sprintf("Coder STUN %d", regionID), |
| 43 | Nodes: []*tailcfg.DERPNode{{ |
| 44 | Name: fmt.Sprintf("%dstun0", regionID), |
| 45 | RegionID: regionID, |
| 46 | HostName: host, |
| 47 | STUNOnly: true, |
| 48 | STUNPort: port, |
| 49 | }}, |
| 50 | }) |
| 51 | } |
| 52 | |
| 53 | return regions, nil |
| 54 | } |
| 55 | |
| 56 | // NewDERPMap constructs a DERPMap from a set of STUN addresses and optionally a remote |
| 57 | // URL to fetch a mapping from e.g. https://controlplane.tailscale.com/derpmap/default. |