Announcement

Collapse
No announcement yet.

Resolve host name to multiple IP

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • #21
    Originally posted by Jerry Wilson View Post

    And to DNS Hijacking.

    As I was playing with low-level DNS agent code, I noticed that obviously bogus URLs (e.g. www.this_is_bogus.com) we're being resolved by Level3 DNS servers to IP addresses 23.202.231.167 and 23.202.231.167. These appear to be belong to Akamai Techologies - a content deliver network (CDN).
    That is not a URL, that is a host name.

    I'm beginning to think that using URLs for client configuration is not worth the effort.
    Then you've never done some decent sysadmin stuff. Using host names (and with that implicit a DNS server) instead of IP addresses let you switch resources around with changing a single line in a text file (that's to what it basically boils down to) at a centralized location (the DNS server), without the need to touch any client. At home, you might get away with IP addresses for your 2 devices. Make that 20 and you'll already begin to experience how tedious any change becomes.

    Comment


    • #22
      Originally posted by Knuth Konrad View Post

      Then you've never done some decent sysadmin stuff. Using host names (and with that implicit a DNS server) instead of IP addresses let you switch resources around with changing a single line in a text file (that's to what it basically boils down to) at a centralized location (the DNS server), without the need to touch any client. At home, you might get away with IP addresses for your 2 devices. Make that 20 and you'll already begin to experience how tedious any change becomes.
      Actually, I've never done any sysadmin stuff - which is why I'm playing with DNS. And DNS name resolution will, almost certainly, be included in the project. A deployment could include many peer routing servers that support a distributed message switching platform. A client host will need to connect to at least one of the servers in order to join the platform.

      DNS hijacking is just another wrinkle that I needed to be aware of - and mitigate (remember, I'm a DNS newbie).

      The client application will probably use the Win32 DnsQueryEx function. I especially like that it supports IPv4 and IPv6, and that it can be called asynchronously. But, to get familiar with the detailed messages that are exchanged between the client and a DNS server, I wrote a "simple" application that works directly at the UDP layer. Because I'm kind of a protocol wonk. And this has been a pretty interesting distraction (e.g. bit-mapped structures, byte order conversions, host name compression in response messages).

      In any case, work continues. The next challenge is to figure how to advertise IP address changes for a host in real time. This will support disaster recovery, and switching from an active to a backup routing server without using really short TTLs in the host A/AAAA records (probably bad form).

      Comment


      • #23
        Jerry
        It may or may not be an issue for you but DnsQueryEX has,
        Minimum supported client Windows 8
        Minimum supported server Windows Server 2012
        and is more complex to use, but it's asynchronous, and you can specify the Name server(s) you want to use.

        as far as getting IPv4 and IPv6

        Plain old DnsQuery can also get those.
        here is an expanded version of the code I posted. (IPv4-Type A, IPv6-Type AAAA, NS, CNAME, MX,, and reverse lookup)
        Code:
        #COMPILE EXE 'PBWIN10    'Jose Roca includes
        #DIM ALL
        '#INCLUDE "WIN32API.INC"
        #INCLUDE "IpTypes.inc"
        #INCLUDE "WinDns.inc"
        #INCLUDE "WS2tcpip.inc"
        
        FUNCTION PBMAIN () AS LONG
        LOCAL lResult    AS LONG
        LOCAL sTemp      AS STRING
        DIM arDNSrec(0)  AS LOCAL ASCIIZ * %MAX_HOSTNAME_LEN
        'Name Servers     using optional parameter to ID type
            lResult = MyDNSQuery ("yahoo.com", %DNS_TYPE_NS,arDNSrec(),2)
            MSGBOX CHOOSE$(lResult, "Query Sucessful" ELSE winerror (lResult)) + $CRLF + JOIN$(arDNSrec(), $CRLF)
        'Mail Servers
            lResult = MyDNSQuery ("powerbasic.com", %DNS_TYPE_MX,arDNSrec())
            MSGBOX CHOOSE$(lResult, "Query Sucessful" ELSE winerror (lResult)) + $CRLF + JOIN$(arDNSrec(), $CRLF)
        'IP4 and CNAME    (Type A IP4 and also return CNAME)
            lResult = MyDNSQuery ("www.yahoo.com", %DNS_TYPE_A,arDNSrec())
            MSGBOX CHOOSE$(lResult, "Query Sucessful" ELSE winerror (lResult)) + $CRLF + JOIN$(arDNSrec(), $CRLF)
        'error test
            lResult = MyDNSQuery ("google.c", %DNS_TYPE_A,arDNSrec())
            MSGBOX CHOOSE$(lResult, "Query Sucessful" ELSE winerror (lResult)) + $CRLF + JOIN$(arDNSrec(), $CRLF)
        'IP6 and CNAME        (Type AAAA IP6 and also return CNAME)
            lResult = MyDNSQuery ("www.att.com", %DNS_TYPE_AAAA,arDNSrec())
            MSGBOX CHOOSE$(lResult, "Query Sucessful" ELSE winerror (lResult)) + $CRLF + JOIN$(arDNSrec(), $CRLF)
        'Reverse Lookup
             lResult = MyDNSQuery ("8.8.8.8", %DNS_TYPE_PTR,arDNSrec())
            MSGBOX CHOOSE$(lResult, "Query Sucessful" ELSE winerror (lResult)) + $CRLF + JOIN$(arDNSrec(), $CRLF)
        
        END FUNCTION
        
        FUNCTION MyDNSQuery (BYREF sDomain AS ASCIIZ,BYVAL DNSType AS LONG ,BYREF arDNSrec() AS ASCIIZ * %MAX_HOSTNAME_LEN, OPT BYVAL TypeID AS LONG) AS LONG
        ' DNSType = %DNS_TYPE_A or %DNS_TYPE_AAAA or %DNS_TYPE_MX or %DNS_TYPE_CNAME  or %DNS_TYPE_NS or %DNS_TYPE_PTR
        'optional TypeID Prepend result with record type, 1 numerically, 2 as text name
        LOCAL lReturn           AS LONG
        LOCAL lpResults         AS DWORD
        LOCAL lpDNSRecord       AS DNS_RECORD PTR
        LOCAL lpARecord         AS DNS_A_DATA PTR
        LOCAL lpMXRecord        AS DNS_MX_DATA PTR
        LOCAL lpPTRRecord       AS DNS_PTR_DATA PTR
        LOCAL lpAAAARecord      AS DNS_AAAA_DATA PTR
        
            IF UBOUND(arDNSrec()) - LBOUND(arDNSrec()) <> -1 THEN
                ERASE arDNSrec()
            END IF
            IF DNSType = %DNS_TYPE_PTR THEN sDomain = PARSE$(sDomain,".",4)+"."+PARSE$(sDomain,".",3)+"."+PARSE$(sDomain,".",2)+"."+PARSE$(sDomain,".",1)+".in-addr.arpa"
        
            lReturn = DnsQuery (sDomain, DNSType, %DNS_QUERY_STANDARD OR %DNS_QUERY_BYPASS_CACHE, BYVAL(0), BYVAL VARPTR(lpDNSRecord), BYVAL(0))
        
            IF lReturn = %ERROR_SUCCESS THEN
                lpResults = lpDNSRecord
                DO WHILE lpDNSRecord <> 0
                     IF UBOUND(arDNSrec()) - LBOUND(arDNSrec()) = -1 THEN
                         REDIM arDNSrec (0 TO 0)
                     ELSE
                         REDIM PRESERVE arDNSrec (0 TO ARRAYATTR (arDNSrec(), 4))
                     END IF
                      IF TypeID = 1 THEN      'optional Prepend result with record type   1 numerically
                          arDNSrec (ARRAYATTR (arDNSrec(), 4) - 1)= "("+FORMAT$(@lpDNSRecord.wType)+ "),"
                      ELSEIF TypeID = 2 THEN  'optional Prepend result with record type   2 as text name
                          arDNSrec (ARRAYATTR (arDNSrec(), 4) - 1)= "("+DNSTypeString(@lpDNSRecord.wType)+ "),"
                      END IF
        
                    SELECT CASE @lpDNSRecord.wType
                       CASE %DNS_TYPE_A                         'IP4 and CNAME
                         lpARecord = VARPTR (@lpDNSRecord.Data)
                         arDNSrec (ARRAYATTR (arDNSrec(), 4) - 1) += IP4NumToString(@lpARecord.IpAddress)
                       CASE %DNS_TYPE_AAAA                      'IP6 and CNAME
                         lpAAAARecord = VARPTR (@lpDNSRecord.Data)
                         arDNSrec (ARRAYATTR (arDNSrec(), 4) - 1) += IP6NumToString (@lpAAAARecord.Ip6Address)
                       CASE %DNS_TYPE_MX                        'Mail Servers
                         lpMXRecord = VARPTR (@lpDNSRecord.Data)
                         arDNSrec (ARRAYATTR (arDNSrec(), 4) - 1) += FORMAT$(@lpMXRecord.wPreference,"00") + "," + @lpMXRecord.@pNameExchange
                       CASE %DNS_TYPE_CNAME                     'CNAME
                         lpPTRRecord = VARPTR (@lpDNSRecord.Data)
                         arDNSrec (ARRAYATTR (arDNSrec(), 4) - 1) += @lpDNSRecord.@pName + " CNAME "  + @lpPTRRecord.@pNameHost
                       CASE %DNS_TYPE_NS                        'Name Servers
                         lpPTRRecord = VARPTR (@lpDNSRecord.Data)
                         arDNSrec (ARRAYATTR (arDNSrec(), 4) - 1) += @lpPTRRecord.@pNameHost
                       CASE %DNS_TYPE_PTR                       'Reverse Lookup
                         lpPTRRecord = VARPTR (@lpDNSRecord.Data)
                         arDNSrec (ARRAYATTR (arDNSrec(), 4) - 1) += @lpPTRRecord.@pNameHost
                    END SELECT
                    lpDNSRecord = @lpDNSRecord.pNext
                LOOP
                DnsRecordListFree (lpResults, %DnsFreeRecordList)
                lReturn = %TRUE
            END IF
            FUNCTION = lReturn
        END FUNCTION
        
        FUNCTION IP4NumToString(BYVAL IP4address AS LONG) AS STRING
          DIM IPAddr  AS BYTE PTR
          IPAddr = VARPTR(IP4address)
          FUNCTION = USING$("#_.#_.#_.#", @IPAddr, @IPAddr[1], @IPAddr[2], @IPAddr[3])
        END FUNCTION
        
        
        FUNCTION IP6NumToString(IP6 AS IP6_ADDRESS) AS STRING
        'Requires
        '#INCLUDE "WinDns.inc"
        '#Include "WS2tcpip.inc"
        LOCAL sIP6 AS STRINGZ * 47
        LOCAL lResult AS DWORD
              lResult = inet_ntop (%AF_INET6, VARPTR(IP6.IP6Word(0)),sIP6, SIZEOF(sIP6))
        FUNCTION = sIP6
        END FUNCTION
        
        
        FUNCTION WinError(BYVAL ErrorCode AS DWORD) AS STRING
         LOCAL pzError  AS ASCIIZ POINTER 'Max is 64K
         LOCAL ErrorLen AS DWORD
         ErrorLen = FormatMessage(%FORMAT_MESSAGE_FROM_SYSTEM OR %FORMAT_MESSAGE_ALLOCATE_BUFFER, _
                                  BYVAL %NULL, ErrorCode, %NULL, BYVAL VARPTR(pzError), %NULL, BYVAL %NULL)
         IF ErrorLen THEN
           REPLACE $CRLF WITH $SPC IN @pzError
           FUNCTION = "Error" & STR$(ErrorCode) & " (0x" & HEX$(ErrorCode) & ") : " & @pzError
           LocalFree(pzError)
         ELSE
           FUNCTION = "Unknown error" & STR$(ErrorCode) & " (0x" & HEX$(ErrorCode) & ")"
         END IF
        END FUNCTION
        
        FUNCTION DnsTypeString(wType AS WORD) AS STRING
         SELECT CASE wType 'DNS Record Types
           CASE %DNS_TYPE_A       : FUNCTION = "A"       '0x0001
           CASE %DNS_TYPE_NS      : FUNCTION = "NS"      '0x0002
           CASE %DNS_TYPE_MD      : FUNCTION = "MD"      '0x0003
           CASE %DNS_TYPE_MF      : FUNCTION = "MF"      '0x0004
           CASE %DNS_TYPE_CNAME   : FUNCTION = "CNAME"   '0x0005
           CASE %DNS_TYPE_SOA     : FUNCTION = "SOA"     '0x0006
           CASE %DNS_TYPE_MB      : FUNCTION = "MB"      '0x0007
           CASE %DNS_TYPE_MG      : FUNCTION = "MG"      '0x0008
           CASE %DNS_TYPE_MR      : FUNCTION = "MR"      '0x0009
           CASE %DNS_TYPE_NULL    : FUNCTION = "NULL"    '0x000a
           CASE %DNS_TYPE_WKS     : FUNCTION = "WKS"     '0x000b
           CASE %DNS_TYPE_PTR     : FUNCTION = "PTR"     '0x000c
           CASE %DNS_TYPE_HINFO   : FUNCTION = "HINFO"   '0x000d
           CASE %DNS_TYPE_MINFO   : FUNCTION = "MINFO"   '0x000e
           CASE %DNS_TYPE_MX      : FUNCTION = "MX"      '0x000f
           CASE %DNS_TYPE_TEXT    : FUNCTION = "TEXT"    '0x0010
           CASE %DNS_TYPE_RP      : FUNCTION = "RP"      '0x0011
           CASE %DNS_TYPE_AFSDB   : FUNCTION = "AFSDB"   '0x0012
           CASE %DNS_TYPE_X25     : FUNCTION = "X25"     '0x0013
           CASE %DNS_TYPE_ISDN    : FUNCTION = "ISDN"    '0x0014
           CASE %DNS_TYPE_RT      : FUNCTION = "RT"      '0x0015
           CASE %DNS_TYPE_NSAP    : FUNCTION = "NSAP"    '0x0016
           CASE %DNS_TYPE_NSAPPTR : FUNCTION = "NSAPPTR" '0x0017
           CASE %DNS_TYPE_SIG     : FUNCTION = "SIG"     '0x0018
           CASE %DNS_TYPE_KEY     : FUNCTION = "KEY"     '0x0019
           CASE %DNS_TYPE_PX      : FUNCTION = "PX"      '0x001a
           CASE %DNS_TYPE_GPOS    : FUNCTION = "GPOS"    '0x001b
           CASE %DNS_TYPE_AAAA    : FUNCTION = "AAAA"    '0x001c
           CASE %DNS_TYPE_LOC     : FUNCTION = "LOC"     '0x001d
           CASE %DNS_TYPE_NXT     : FUNCTION = "NXT"     '0x001e
           CASE %DNS_TYPE_EID     : FUNCTION = "EID"     '0x001f
           CASE %DNS_TYPE_NIMLOC  : FUNCTION = "NIMLOC"  '0x0020
           CASE %DNS_TYPE_SRV     : FUNCTION = "SVR"     '0x0021
           CASE %DNS_TYPE_ATMA    : FUNCTION = "ATMA"    '0x0022
           CASE %DNS_TYPE_NAPTR   : FUNCTION = "NAPTR"   '0x0023
           CASE %DNS_TYPE_KX      : FUNCTION = "KX"      '0x0024
           CASE %DNS_TYPE_CERT    : FUNCTION = "CERT"    '0x0025
           CASE %DNS_TYPE_A6      : FUNCTION = "A6"      '0x0026
           CASE %DNS_TYPE_DNAME   : FUNCTION = "DNAME"   '0x0027
           CASE %DNS_TYPE_SINK    : FUNCTION = "SINK"    '0x0028
           CASE %DNS_TYPE_OPT     : FUNCTION = "OPT"     '0x0029
           CASE %DNS_TYPE_DS      : FUNCTION = "DS"      '0x002B
           CASE %DNS_TYPE_RRSIG   : FUNCTION = "RSIG"    '0x002E
           CASE %DNS_TYPE_NSEC    : FUNCTION = "NSEC"    '0x002F
           CASE %DNS_TYPE_DNSKEY  : FUNCTION = "DNSKEY"  '0x0030
           CASE %DNS_TYPE_DHCID   : FUNCTION = "DHCID"   '0x0031
           CASE %DNS_TYPE_UINFO   : FUNCTION = "UINFO"   '0x0064
           CASE %DNS_TYPE_UID     : FUNCTION = "UID"     '0x0065
           CASE %DNS_TYPE_GID     : FUNCTION = "DIG"     '0x0066
           CASE %DNS_TYPE_UNSPEC  : FUNCTION = "UNSPEC"  '0x0067
           CASE %DNS_TYPE_ADDRS   : FUNCTION = "ADDRS"   '0x00f8
           CASE %DNS_TYPE_TKEY    : FUNCTION = "TKEY"    '0x00f9
           CASE %DNS_TYPE_TSIG    : FUNCTION = "TSIG"    '0x00fa
           CASE %DNS_TYPE_IXFR    : FUNCTION = "IXFR"    '0x00fb
           CASE %DNS_TYPE_AXFR    : FUNCTION = "AXFR"    '0x00fc
           CASE %DNS_TYPE_MAILB   : FUNCTION = "MAILB"   '0x00fd
           CASE %DNS_TYPE_MAILA   : FUNCTION = "MAILA"   '0x00fe
           CASE %DNS_TYPE_ALL     : FUNCTION = "ALL"     '0x00ff
           CASE %DNS_TYPE_ANY     : FUNCTION = "ANY"     '0x00ff
           CASE %DNS_TYPE_WINS    : FUNCTION = "WINS"    '0xff01
           CASE %DNS_TYPE_WINSR   : FUNCTION = "WINSR"   '0xff02
           CASE %DNS_TYPE_NBSTAT  : FUNCTION = "NBSTAT"  '0xNS_TYPE_WINSR
         END SELECT
        
        END FUNCTION

        Comment


        • #24
          Originally posted by Jerry Wilson View Post

          Actually, I've never done any sysadmin stuff - which is why I'm playing with DNS. And DNS name resolution will, almost certainly, be included in the project. A deployment could include many peer routing servers that support a distributed message switching platform. A client host will need to connect to at least one of the servers in order to join the platform.

          DNS hijacking is just another wrinkle that I needed to be aware of - and mitigate (remember, I'm a DNS newbie).
          Yes and no.

          We (you) need to distinguish about what type of DNS server we're talking: 1) public DNS servers or 2) organizational internal DNS servers

          For 1) awareness that such a thing exists is good. But there isn't much anyone can do about. If someone manages to poison public DNS servers (the ones of your ISP or Google's or CloudFlare's), all of us are f'ed.

          2) Any organization running a own network utilizes most likely their own internal DNS servers. These DNS servers are the ones that the clients contact. DNS servers on the clients can only be configured with administrative privileges. For every DNS zone (think: "domain") hosted on these servers, they will answer the request from that zone. For every unknown zone, they a) forward the client's request to the configured forwarders (=external, public DNS servers) and b) upon receiving an answer, cache that for a bit.

          In a Windows network environment, those internal DNS servers typically are located on the domain controllers (DC), which is the core and heart of the organization. These servers should only be accessible by accounts with domain administrator privilege. By now you might already know where the real danger looms: if someone is able to poison the entity's internal DNS server, either by manipulating the clients' DNS setting and pointing them to a rogue server or manipulating the org's actual DNS servers, you're doomed already, because someone managed to sneak into the network and managed to get administrative access. That's the key to the kingdom right there.

          Comment


          • #25
            Rod,

            One of the things that I'm trying to avoid is blocking on a DNS query call while Windows is waiting for a response. It appears that this can be up to 10 seconds (5 attempts with timeouts of 1, 1, 2, 4 and 2 seconds) which, for this application, is kind of important to avoid. I want to either 1) continue doing stuff while the DnsQueryEX function completes and calls me back (pass or fail) or 2) use my own DNS client, which accepts an argument for how long to wait for a response (e.g. 2 tries with 1, 2 second timeouts) and alternates between multiple DNS servers until if gets a response. The latter also uses a callback to notify the calling app of the status of the query.

            What I'm curious about is how DnsQueryEX uses the list of DNS servers it's provided. Does it query them in a serial process - waiting up to 10 seconds for each to respond? Or does it concurrently query the multiple DNS servers and wait for one of them to provide a result? I haven't chased this too much but, if I can't find a description someplace, I can always use DNSQureyEX and Wireshark to figure it out.

            BTW: Thanks for the reference to the inet_pton and inet_ntop functions. I've been using RtlIpv6StringToAddress, etc. from ntdll.dll but this seems more convenient.

            Comment


            • #26
              Knuth,

              I think that we're thinking the same thing. One thought is that, when a client queries public DNS servers to resolve a target host name (e.g. svr1.mynet.com, svr2.mynet.com), DNS will return an SOA record that the client will then use to query an authoritative zone DNS server (*.mynet.com). The zone server will then resolve the specific requested host name. The zone servers should be pretty static so TTL values for those servers/records that are cached in the public DNS servers can be large enough to reduce queries on the public DNS network. The TTLs for the specific host A/AAAA records in the zone DNS servers can have very short TTLs which will allow IP addresses be changed quickly (disaster recovery). And the zone database/DNS servers will be protected in hosts controlled by the network manager/service provider.

              And I believe that you're correct about the dangers in the DNS environment. If a nefarious entity starts fiddling with public DNS servers or breaches the zone DNS servers, all bets are off. This seems to be a sysadmin thing - which, hopefully, the network manager understands and monitors.

              Comment


              • #27
                BTW, in comparison to DNS poisoning, tampering with the much more important (on a global scale) BGP is absurdly easy.

                tl;dr
                Oversimplified: one just broadcasts "these IP ranges now belong to me, route 'em here". That's it. No hacking involved. That's the official way to handle it. Here's the (scary?) part to know about BGP:
                Although security extensions are available for BGP, and third-party route DB resources exist for validating routes, by default the BGP protocol is designed to trust all route announcements sent by peers, and few ISPs rigorously enforce checks on BGP
                Just so you have another nightmare to worry about.

                Comment

                Working...
                X