Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature Request]: Name resolution #207

Closed
tiredofit opened this issue Nov 15, 2023 · 1 comment
Closed

[Feature Request]: Name resolution #207

tiredofit opened this issue Nov 15, 2023 · 1 comment
Labels
enhancement New feature or request pinned Does not stale

Comments

@tiredofit
Copy link

🚀 Feature Summary

Be able to resolve names similar to ZTCentral API zeronsd

📝 Detailed Description

I am just getting started with ZT and ZTNet and trying to understand DNS a bit better.

I see the start of a PR #63 and understand the concept of how it generally works.
I'm able to pull information from a ZT selfhosted controller, however it does not reveal any details related to name. I see through on the ZT Forums that others share a request to set a "name=value" upon joining a network, alas, I think this needs to be via ZTNET-UI

I suppose what would really be required would be ZeroTier Central API compatibility to output details on the hosts which theoretically should be able to provide details on host authorized, ip address, and hostname.

In my case I don't necessarily need to use ZeroNSD, as I could pull and write the scripts to pull from the ZT_Net API easy enough.

I modified a script I found on the internet to support pulling details from a local controller, and would just need to add in the ZTNET API details to be able to output a "hosts" file.

The script
#!/usr/bin/env bash

# zt2hosts: contact a ZeroTier One API controller, and convert a list of
# authorized network members to hosts(5) format

# Modified by tiredofit@github 2023-11-15 to support local controllers

# Syntax: script zerotier_network_id:dnssuffix

API_ADDRESS=${API_ADDRESS:-"http://localhost:9993"}
API_URL="${API_ADDRESS}/controller"
AUTH_HEADER="X-ZT1-AUTH:"

## -----------------------------------------------------------------------------

set -eo pipefail

if [ -z "${ZT_API_TOKEN}" ] && [ ! -f "/var/lib/zerotier-one/authtoken.secret" ]; then
    echo "ERROR: must set ZT_API_TOKEN! or have a token in /var/lib/zerotier-one/authtoken.secret"
    exit 1
elif [ -n "${ZT_API_TOKEN}" ]; then
    AUTH_TOKEN="${ZT_API_TOKEN}"
elif [ -f "/var/lib/zerotier-one/authtoken.secret" ] ; then
    AUTH_TOKEN="$(sudo cat /var/lib/zerotier-one/authtoken.secret)"
fi

if [ -z "${1}" ] ; then
    echo "ERROR: must provide at least one network ID!"
    echo "Syntax: $(basename $0) <network_id>:dns_suffix"
    exit 1
fi

get_network_info() { curl -sH "${AUTH_HEADER} ${AUTH_TOKEN}" "$API_URL/network/${1}"; }
get_network_members() { curl -sH "${AUTH_HEADER} ${AUTH_TOKEN}" "${API_URL}/network/${1}/member"; }
get_network_member_info() { curl -sH "${AUTH_HEADER} ${AUTH_TOKEN}" "${API_URL}/network/${1}/member/${2}"; }

print_ipv6_id() {
    printf "%s:%s:%s" \
        "$(echo "${1}" | cut -c1-2)" \
        "$(echo "${1}" | cut -c3-6)" \
        "$(echo "${1}" | cut -c7-10)"
}

print_rfc4193() {
    printf "fd%s:%s:%s:%s:%s99:93%s" \
        "$(echo "${2}" | cut -c1-2)" \
        "$(echo "${2}" | cut -c3-6)" \
        "$(echo "${2}" | cut -c7-10)" \
        "$(echo "${2}" | cut -c11-14)" \
        "$(echo "${2}" | cut -c15-16)" \
        "$(print_ipv6_id "${1}")"
}

print_6plane() {
    local TOP=${2:0:8}
    local BOT=${2:9:16}
    local hashed=$(printf '%x\n' "$(( 0x$TOP ^ 0x$BOT ))")

    printf "fc%s:%s:%s%s:0000:0000:0001" \
        $(echo "${hashed}" | cut -c1-2) \
        $(echo "${hashed}" | cut -c3-6) \
        $(echo "${hashed}" | cut -c7-8) \
        $(print_ipv6_id "${1}")
}

## -----------------------------------------------------------------------------

ipv4_lines=("127.0.0.1 localhost")
ipv6_lines=("::1       localhost ip6-localhost ip6-loopback")

for NETWORK in ${@}; do
    mapfile -td \: fields < <(printf "%s\0" "${NETWORK}")
    DNSNAME="${fields[0]}"
    NETWORK="${fields[1]}"

    network_info=$(get_network_info "${NETWORK}")

    network_ipv6conf=$(echo "${network_info}" | jq -c '.v6AssignMode')
    network_sixplane=$(echo "${network_ipv6conf}" | jq -r '.["6plane"]')
    network_rfc4193=$(echo "${network_ipv6conf}" | jq -r '.rfc4193')
    network_members=$(get_network_members "${NETWORK}")
    network_members_joined=$(echo "${network_members}" | jq keys)

    for network_member in $(echo "${network_members_joined}" | jq -c -r '.[]'); do
        network_member_info=$(get_network_member_info "${NETWORK}" "${network_member}" | jq '. | select(.authorized == true)')
        if [ -n "${network_member_info}" ] ; then
            network_member_id=$(echo "${network_member_info}" | jq -r '.id')

            ipv4_line=$(printf "%s\t%s.%s\t%s" \
                "$(echo "${network_member_info}" | jq -r '.ipAssignments[0]')" \
                "$(echo "${network_member_info}" | jq -r '.name')" \
                "$DNSNAME" \
                "${network_member_id}.$DNSNAME")
                ipv4_lines+=("${ipv4_line}")

            if [ "${network_rfc4193}" = "true" ]; then
                ipv6_line=$(printf "%s\t%s.%s\t%s" \
                    "$(print_rfc4193 "${network_member_id}" "${NETWORK}")" \
                    "$(echo "${network_member_info}" | jq -r '.name')" \
                    "$DNSNAME" \
                    "${network_member_id}.$DNSNAME")
                ipv6_lines+=("${ipv6_line}")
            fi

            if [ "${network_sixplane}" = "true" ]; then
                ipv6_line=$(printf "%s\t%s.%s\t%s" \
                    "$(print_6plane "$network_member_id}" "${NETWORK}")" \
                    "$(echo "${network_member_info}" | jq -r '.name')" \
                    "$DNSNAME" \
                    "${network_member_id}.$DNSNAME")
                ipv6_lines+=("${ipv6_line}")
            fi
        fi
    done
done

(
  for ipv4_entry in "${ipv4_lines[@]}"; do printf "%s\n" "${ipv4_entry}"; done
  for ipv6_entry in "${ipv6_lines[@]}"; do printf "%s\n" "${ipv6_entry}"; done
) | awk -vOFS='\t' 'NF > 0 { $1 = $1 } 1'

🎯 Use Case

This would allow to resolve names in DNS

💡 Willing to Contribute

Yes, I could help with testing

@tiredofit tiredofit added the enhancement New feature or request label Nov 15, 2023
@sinamics sinamics added the pinned Does not stale label Nov 16, 2023
@sinamics sinamics mentioned this issue Dec 9, 2023
3 tasks
@sinamics
Copy link
Owner

sinamics commented Dec 9, 2023

Will be available in next version.
https://ztnet.network/usage/create_dns_host

@sinamics sinamics closed this as completed Dec 9, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request pinned Does not stale
Projects
None yet
Development

No branches or pull requests

2 participants