Skip to content

FQDN on Windows is unreachable #12560

Open
@externl

Description

@externl

Description

Hello, we've been running into various hostname/dns related issues on Windows and macOS for the last few weeks. This one is for Windows specifically.

The FQDN (as reported by Python) is unreachable.

hostname = socket.gethostname()
fqdn = socket.getfqdn()
Hostname: runnervmk2jw4
Ping to hostname runnervmk2jw4: successful

IP addresses for runnervmk2jw4:
  10.1.0.105
  fe80::3e59:29d0:86a2:da4a
  fe80::cce:3a6f:9359:9b32
  172.20.80.1

Pinging IP addresses for runnervmk2jw4:
  Ping to 10.1.0.105: successful
  Ping to fe80::3e59:29d0:86a2:da4a: successful
  Ping to fe80::cce:3a6f:9359:9b32: successful
  Ping to 172.20.80.1: successful

==================================================

FQDN: runnervmk2jw4.askkogcowbeexaxaijjtd4dtkg.cx.internal.cloudapp.net
Ping to fqdn runnervmk2jw4.askkogcowbeexaxaijjtd4dtkg.cx.internal.cloudapp.net: failed

IP addresses for runnervmk2jw4.askkogcowbeexaxaijjtd4dtkg.cx.internal.cloudapp.net:
  10.1.0.103

Pinging IP addresses for runnervmk2jw4.askkogcowbeexaxaijjtd4dtkg.cx.internal.cloudapp.net:
  Ping to 10.1.0.103: failed

As you can see the FQDN does not resolve to an ip address associated with the Windows runner.

Run from my test repo here: https://github.com/externl/sandbox/actions/runs/16176086721/job/45661454665

Platforms affected

  • Azure DevOps
  • GitHub Actions - Standard Runners
  • GitHub Actions - Larger Runners

Runner images affected

  • Ubuntu 22.04
  • Ubuntu 24.04
  • macOS 13
  • macOS 13 Arm64
  • macOS 14
  • macOS 14 Arm64
  • macOS 15
  • macOS 15 Arm64
  • Windows Server 2019
  • Windows Server 2022
  • Windows Server 2025

Image version and build link

Runner Image
  Image: windows-2022
  Version: 20250701.1.0
  Included Software: https://github.com/actions/runner-images/blob/win22/20250701.1/images/windows/Windows2022-Readme.md
  Image Release: https://github.com/actions/runner-images/releases/tag/win22%2F20250701.1

Is it regression?

Yes, this used to work.

Expected behavior

FQDN should resolve to an IP associated with runner.

Actual behavior

FQDN resolves to IP not associated with runner.

Repro steps

Get fqdn on Windows using Python and try to ping it.

socket.getfqdn()

You can also use this script I threw together:

#!/usr/bin/env python3

import socket
import platform
import subprocess
import sys


def get_ips_for_hostname(hostname):
    """Get all IP addresses associated with the hostname."""
    try:
        # Get both IPv4 and IPv6 addresses
        addrinfo = socket.getaddrinfo(hostname, None)
        # Extract unique IP addresses
        ip_addresses = set()
        for addr in addrinfo:
            ip = addr[4][0]
            ip_addresses.add(ip)
        return list(ip_addresses)
    except socket.gaierror:
        return []


def ping_target(target):
    """
    Ping a target (hostname or IP) and return whether it was successful.

    Args:
        target (str): The hostname or IP address to ping

    Returns:
        bool: True if ping was successful, False otherwise
    """
    # Adjust ping command based on operating system
    param = "-n" if platform.system().lower() == "windows" else "-c"
    command = ["ping", param, "1", target]

    try:
        result = subprocess.run(
            command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True
        )
        return result.returncode == 0
    except Exception as e:
        print(f"Error pinging {target}: {e}")
        return False


def run_checks_for_target(target_name, target_value):
    """Run all checks for a given target (hostname or FQDN).

    Returns:
        bool: True if all checks passed, False if any failed
    """
    print(f"{target_name}: {target_value}")
    has_failures = False

    # Ping the target directly
    ping_success = ping_target(target_value)
    ping_status = "successful" if ping_success else "failed"
    print(f"Ping to {target_name.lower()} {target_value}: {ping_status}")
    if not ping_success:
        has_failures = True

    print()
    # Get IPs for the target
    ips = get_ips_for_hostname(target_value)

    if not ips:
        print(f"No IP addresses found for {target_value}")
        return False

    print(f"IP addresses for {target_value}:")
    for ip in ips:
        print(f"  {ip}")

    # Ping each IP
    print(f"\nPinging IP addresses for {target_value}:")
    for ip in ips:
        success = ping_target(ip)
        status = "successful" if success else "failed"
        print(f"  Ping to {ip}: {status}")
        if not success:
            has_failures = True

    return not has_failures


def main():
    # Get hostname and FQDN
    hostname = socket.gethostname()
    fqdn = socket.getfqdn()

    all_passed = True

    # Run checks for hostname
    hostname_passed = run_checks_for_target("Hostname", hostname)
    if not hostname_passed:
        all_passed = False

    print("\n" + "=" * 50 + "\n")

    # Run checks for FQDN (only if different from hostname)
    if fqdn != hostname:
        fqdn_passed = run_checks_for_target("FQDN", fqdn)
        if not fqdn_passed:
            all_passed = False
    else:
        print(f"FQDN is the same as hostname: {fqdn}")

    # Exit with appropriate status code
    if not all_passed:
        print("\nSome checks failed. Exiting with status code 1.")
        sys.exit(1)
    else:
        print("\nAll checks passed.")
        sys.exit(0)


if __name__ == "__main__":
    main()

Metadata

Metadata

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions