gateway-domain: tag:orchestrator is now allowed by the ACL too
A rule was added so the testing gateway may also reach nodes tagged tag:orchestrator, not only tag:notplants-test-server. Both tags now appear in the skill's table, and the tool's warning fires only when a node carries neither. Verified end to end from an orchestrator box (tag:orchestrator, tag:server) rather than assumed: - the gateway can open a TCP connection to it over the tailnet - a request to https://acltest.gtest.commoninternet.net/ returns the box's own self-signed certificate, subject and issuer both CN=acltest..., which is only possible if the gateway proxied the stream instead of terminating it - the payload came back and the box's listener logged the request The troubleshooting section gains the one-liner that isolates this from the gateway itself: open a TCP connection to your backend from the gateway.
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
name: gateway-domain
|
name: gateway-domain
|
||||||
description: Give a tailnet box a real public HTTPS domain (<name>.gtest.commoninternet.net) by mapping it on the shared testing gateway. Use when an agent needs a publicly reachable URL for a box with no public IP — an OAuth callback, a webhook receiver, a demo link, an ACME challenge. Covers the add/remove tool, where the admin password lives, and the two things that silently break it: your box must carry the tag:notplants-test-server tailnet tag or the ACL blocks the gateway from reaching it, and your box serves the TLS cert rather than the gateway.
|
description: Give a tailnet box a real public HTTPS domain (<name>.gtest.commoninternet.net) by mapping it on the shared testing gateway. Use when an agent needs a publicly reachable URL for a box with no public IP — an OAuth callback, a webhook receiver, a demo link, an ACME challenge. Covers the add/remove tool, where the admin password lives, and the two things that silently break it: your box must carry a tailnet tag the ACL allows (tag:notplants-test-server or tag:orchestrator) or the gateway cannot reach it, and your box serves the TLS cert rather than the gateway.
|
||||||
---
|
---
|
||||||
|
|
||||||
# Giving your box a public domain
|
# Giving your box a public domain
|
||||||
@@ -18,20 +18,26 @@ python3 engine/tools/gateway-domain.py add myapp
|
|||||||
That is the whole happy path. The backend defaults to **this box's own tailscale IP**, so run
|
That is the whole happy path. The backend defaults to **this box's own tailscale IP**, so run
|
||||||
it on the machine that will serve the domain.
|
it on the machine that will serve the domain.
|
||||||
|
|
||||||
## Your box must carry the `notplants-test-server` tag
|
## Your box needs a tailnet tag the ACL allows
|
||||||
|
|
||||||
The tailnet ACL only permits the gateway to open connections to nodes tagged
|
The gateway can only open connections to nodes the tailnet ACL lets it reach. Two tags qualify:
|
||||||
**`tag:notplants-test-server`**. Without it the gateway accepts your mapping and then simply
|
|
||||||
never connects — which looks like a broken gateway and is not one. Check before you start:
|
| tag | who |
|
||||||
|
|---|---|
|
||||||
|
| `tag:notplants-test-server` | test servers — the usual case |
|
||||||
|
| `tag:orchestrator` | orchestrator boxes (added 2026-08-20, verified end to end) |
|
||||||
|
|
||||||
|
Without one of them the gateway accepts your mapping and then simply never connects — which
|
||||||
|
looks like a broken gateway and is not one. Check before you start:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
tailscale status --json | jq -r '.Self.Tags[]?'
|
tailscale status --json | jq -r '.Self.Tags[]?'
|
||||||
```
|
```
|
||||||
|
|
||||||
If `tag:notplants-test-server` is not listed, add it to that node in the Tailscale admin (a
|
If neither tag is listed, add one to that node in the Tailscale admin (a node's tags are set
|
||||||
node's tags are set when it is authenticated, so this may mean re-authenticating it), or map a
|
when it is authenticated, so this may mean re-authenticating it), or map a backend that already
|
||||||
backend that already has the tag. `gateway-domain.py` warns when the node it is about to map
|
has one. `gateway-domain.py` warns when the node it is about to map carries neither, but it
|
||||||
lacks the tag, but it cannot see the tags of a backend you name explicitly — that one is on you.
|
cannot see the tags of a backend you name explicitly — that one is on you.
|
||||||
|
|
||||||
The gateway itself is tagged `tag:testing-gateway`; that is the other half of the same ACL rule.
|
The gateway itself is tagged `tag:testing-gateway`; that is the other half of the same ACL rule.
|
||||||
|
|
||||||
@@ -134,10 +140,12 @@ Check in this order — most failures are the last two.
|
|||||||
|
|
||||||
1. `gateway-domain.py list` — is the mapping actually there?
|
1. `gateway-domain.py list` — is the mapping actually there?
|
||||||
2. `getent hosts myapp.gtest.commoninternet.net` — should be `49.13.156.72`.
|
2. `getent hosts myapp.gtest.commoninternet.net` — should be `49.13.156.72`.
|
||||||
3. **Is your node tagged `tag:notplants-test-server`?** (`tailscale status --json | jq -r
|
3. **Does your node carry `tag:notplants-test-server` or `tag:orchestrator`?**
|
||||||
'.Self.Tags[]?'`) This is the single most common cause. The gateway is `gateway-test-1`
|
(`tailscale status --json | jq -r '.Self.Tags[]?'`) This is the single most common cause.
|
||||||
(`100.91.44.90`), tagged `tag:testing-gateway`; the ACL pairs those two tags, so an
|
The gateway is `gateway-test-1` (`100.91.44.90`), tagged `tag:testing-gateway`; the ACL
|
||||||
untagged backend is unreachable no matter how correct the mapping looks.
|
pairs that with the tags above, so a backend with neither is unreachable no matter how
|
||||||
|
correct the mapping looks. Quick check from the gateway itself:
|
||||||
|
`ssh root@49.13.156.72 'timeout 5 bash -c "echo > /dev/tcp/<your-tailnet-ip>/<port>"'`
|
||||||
4. **Is your service actually serving TLS for that name on the backend port?** A backend that
|
4. **Is your service actually serving TLS for that name on the backend port?** A backend that
|
||||||
speaks plain HTTP on 443, or serves a cert for a different name, fails here and nowhere else.
|
speaks plain HTTP on 443, or serves a cert for a different name, fails here and nowhere else.
|
||||||
|
|
||||||
|
|||||||
@@ -97,10 +97,10 @@ _ERR = re.compile(r'<p style="color:red">(.*?)</p>', re.S)
|
|||||||
# /var/lib/tunnel-gateway/tunnel_map.conf can clear. Refuse to create one.
|
# /var/lib/tunnel-gateway/tunnel_map.conf can clear. Refuse to create one.
|
||||||
_BACKEND = re.compile(r"^(\d{1,3}(?:\.\d{1,3}){3})(?::(\d{1,5}))?$")
|
_BACKEND = re.compile(r"^(\d{1,3}(?:\.\d{1,3}){3})(?::(\d{1,5}))?$")
|
||||||
|
|
||||||
# The tailnet ACL only lets the gateway open connections to nodes carrying this tag.
|
# The tailnet ACL only lets the gateway open connections to nodes carrying one of these.
|
||||||
# A mapping to an untagged node is accepted by the gateway and then simply never
|
# A mapping to an untagged node is accepted by the gateway and then simply never
|
||||||
# connects, which looks like a gateway fault and is not one.
|
# connects, which looks like a gateway fault and is not one.
|
||||||
REQUIRED_TAG = "tag:notplants-test-server"
|
ALLOWED_TAGS = ("tag:notplants-test-server", "tag:orchestrator")
|
||||||
|
|
||||||
|
|
||||||
def _validate_backend(backend):
|
def _validate_backend(backend):
|
||||||
@@ -144,9 +144,10 @@ def _warn_untagged(exe):
|
|||||||
tags = _self_tags(exe)
|
tags = _self_tags(exe)
|
||||||
if tags is None:
|
if tags is None:
|
||||||
return
|
return
|
||||||
if REQUIRED_TAG not in tags:
|
if not any(t in tags for t in ALLOWED_TAGS):
|
||||||
print(
|
print(
|
||||||
f"warning: this node is not tagged {REQUIRED_TAG} (tags: {', '.join(tags) or 'none'}).\n"
|
f"warning: this node carries none of {' / '.join(ALLOWED_TAGS)} "
|
||||||
|
f"(tags: {', '.join(tags) or 'none'}).\n"
|
||||||
" The gateway will accept the mapping but the tailnet ACL will not let it\n"
|
" The gateway will accept the mapping but the tailnet ACL will not let it\n"
|
||||||
" reach this box, so no traffic will flow. Add the tag in the Tailscale\n"
|
" reach this box, so no traffic will flow. Add the tag in the Tailscale\n"
|
||||||
" admin, or map a backend that already has it.",
|
" admin, or map a backend that already has it.",
|
||||||
|
|||||||
Reference in New Issue
Block a user