openziti / ziti-tunnel-sdk-c

Apache License 2.0
43 stars 16 forks source link

Handle proxy dns responses correctly #827

Closed scareything closed 6 months ago

scareything commented 6 months ago

There were two issues that prevented proxied dns queries from working:

  1. The ziti connection that dns queries are sent over is not established (by design) when the first request is sent with ziti_write. The intent is to rely on ziti_write queueing the message until the connection is established, but there was a problem in ziti-sdk-c that caused crypto hash checks to fail for messages that were sent before the connection was ready. This was fixed with ziti-sdk-c 0.36.9.
  2. The write callback associated with sending the dns query to the hosting tunneler was incorrectly treating the "length" parameter as "status", so even when a message was sent successfully, the tsdk responded to the original DNS client with SRVFAIL.
qrkourier commented 6 months ago

To test this I need a Ziti service that proxies DNS queries to a nameserver that's the target of a host config, correct?

scareything commented 6 months ago

You just need a service that:

Create identities that intercept and host this service, and send an MX query through the dns server of the intercepting tunneler. You can do this with the host command:

host test.wcdomain.ziti 100.64.0.2

Note the service does not need to be for DNS. In fact you don't even need to use the service ports at all. The intercepting tunneler makes a ziti connection for itself specifically for carrying proxied dns queries. This feature is implicitly enabled when wildcard domains are being intercepted, and allows MX and TXT records for wildcard domains to be resolved at the hosting tunneler for the service.

qrkourier commented 6 months ago

It worked for me!

I was able to build this branch with an unreleased revision of the ziti-builder image. The latest release's vcpkg checkout is tool old.

On that branch, I needed to build the builder.

docker build . -t openziti/ziti-builder:local

Then I could run the builder with this repo's cross-building script.

ZITI_BUILDER_TAG=local ./scripts/ziti-builder.sh

With that build from this branch and the following Ziti service, I was able to reach a remote API by looking up a domain name that matched the wildcard intercept.

(set -euxo pipefail;

ZITI_SIMPLE=wildcard
ZITI_SIMPLE_CLIENT_PORT=443
ZITI_SIMPLE_HOST_PORT=443
ZITI_SIMPLE_HOST_ADDRESS=*.default.svc

ziti edge update identity "miniziti-client" \
    --role-attributes ${ZITI_SIMPLE}-clients

ziti edge update identity "miniziti-router" \
    --role-attributes ${ZITI_SIMPLE}-hosts

ziti edge delete config "${ZITI_SIMPLE}-intercept-config"
ziti edge create config "${ZITI_SIMPLE}-intercept-config" intercept.v1 \
    '{"protocols":["tcp"],"addresses":["'${ZITI_SIMPLE_HOST_ADDRESS}'"], "portRanges":[{"low":'${ZITI_SIMPLE_CLIENT_PORT}', "high":'${ZITI_SIMPLE_CLIENT_PORT}'}]}'

ziti edge delete config "${ZITI_SIMPLE}-host-config"
ziti edge create config "${ZITI_SIMPLE}-host-config" host.v1 \
    '{"protocol":"tcp", "forwardAddress": true, "allowedAddresses":["'${ZITI_SIMPLE_HOST_ADDRESS}'"],"port":'${ZITI_SIMPLE_HOST_PORT}'}'

ziti edge delete service "${ZITI_SIMPLE}-service"
ziti edge create service "${ZITI_SIMPLE}-service" \
   --configs "${ZITI_SIMPLE}-intercept-config,${ZITI_SIMPLE}-host-config"

ziti edge delete service-policy "${ZITI_SIMPLE}-bind-policy"
ziti edge create service-policy "${ZITI_SIMPLE}-bind-policy" Bind \
    --service-roles "@${ZITI_SIMPLE}-service" --identity-roles "#${ZITI_SIMPLE}-hosts"

ziti edge delete service-policy "${ZITI_SIMPLE}-dial-policy"
ziti edge create service-policy "${ZITI_SIMPLE}-dial-policy" Dial \
    --service-roles "@${ZITI_SIMPLE}-service" --identity-roles "#${ZITI_SIMPLE}-clients"

;)