Author Topic: Retrieve your External IP address  (Read 17943 times)

Offline AIR

  • BASIC Developer
  • Posts: 932
  • Coder
Re: Retrieve your External IP address
« Reply #15 on: March 21, 2019, 01:00:40 AM »
MBC:

Code: Text
  1. $EXECON "-lresolv"
  2.  
  3. $HEADER
  4.     #include <resolv.h>
  5.     #include <arpa/inet.h>
  6.     #include <netdb.h>
  7. $HEADER
  8.  
  9. Const query = "myip.opendns.com"
  10.  
  11. dim he as hostent PTR, addr_list as in_addr PTR PTR, i
  12. dim res as __res_state, addr as in_addr, answer[512] as UCHAR
  13. dim ip$,length,handle as ns_msg, rr as ns_rr
  14.  
  15. he = gethostbyname( "resolver1.opendns.com" )
  16. addr_list = (in_addr **) he->h_addr_list
  17. ip$ = inet_ntoa(*addr_list[0])
  18.  
  19. res_ninit(&res)
  20. inet_aton(ip$, &addr)
  21. res.nsaddr_list[0].sin_addr = addr
  22. res.nsaddr_list[0].sin_family = AF_INET;
  23. res.nsaddr_list[0].sin_port = htons(NS_DEFAULTPORT);
  24. res.nscount = 1;
  25.  
  26. length = res_nquery(&res, query, ns_c_in, ns_t_a, answer, sizeof(answer))
  27. ns_initparse(answer, length, &handle)
  28. if ns_msg_count(handle, ns_s_an) > 0 then
  29.     if ns_parserr(&handle, ns_s_an, 0, &rr) = 0 then
  30.         ip$ = inet_ntoa(*(in_addr *)ns_rr_rdata(rr))
  31.     endif
  32. endif
  33.  
  34. print "External IP: ",ip$
  35.  

AIR.

Offline AIR

  • BASIC Developer
  • Posts: 932
  • Coder
Re: Retrieve your External IP address
« Reply #16 on: March 23, 2019, 11:33:09 AM »
I would like to see an example using raw sockets without the support libraries hiding what is really going on.

Here's what that would look like in Python:

Code: Python
  1. #!/usr/bin/env python
  2.  
  3. import socket, sys
  4.    
  5. if __name__ == '__main__':
  6.  
  7.     server = (socket.gethostbyname("resolver1.opendns.com"), 53)
  8.  
  9.     prefix = "\x41\x41\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00"
  10.     suffix = "\x00\x00\x01\x00\x01"
  11.     message = "\x04\x6d\x79\x69\x70\x07\x6f\x70\x65\x6e\x64\x6e\x73\x03\x63\x6f\x6d"
  12.  
  13.     query = ''.join( (prefix,message,suffix) )
  14.  
  15.     try:
  16.         sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
  17.         sock.settimeout(5)
  18.         sock.sendto(query, server)             
  19.         data, addr = sock.recvfrom(512)
  20.     except Exception, e:
  21.         print "No response from server", server,e
  22.         sock.close()
  23.         sys.exit()
  24.    
  25.     # get the response from the server 
  26.     response = str(data.split(',', 0)[0].encode("hex"))
  27.    
  28.     # check the RCODE value
  29.     if int(response[7:8]) == 0: # no error, get the ip address 
  30.  
  31.         # get the answer section from the server response
  32.         answer = response[2*len(query)+24:]    
  33.  
  34.         # get the RDATA from the answer
  35.         rdata = answer[:8]
  36.  
  37.         a = int(rdata, 16)     
  38.  
  39.         # convert result to human readable IP
  40.         ipaddress = '.'.join([ str(x) for x in (a >> 24 & 0xff, a >> 16 & 0xff, a >> 8 & 0xff, a & 0xff)])
  41.  
  42.         # Output the ipaddress
  43.         print "External IP: ", ipaddress
  44.  
  45.  
  46.     else:
  47.         # Catch-All error message
  48.         print "Error Communicating with Server"
  49.     sock.close()
  50.  

Couple of notes:

I hand-crafted the binary query/request that is sent to the dns server.  The alternative would have required the use of the "structs" or "binascii" modules.

AFAIK, SB Sockets are TCP only, so I don't think using Sockets there will work since this requires a UDP connection.

This works under macOS, Linux, and RasPi at this point.

AIR.

Offline John

  • Forum Support / SB Dev
  • Posts: 3597
    • ScriptBasic Open Source Project
Re: Retrieve your External IP address
« Reply #17 on: March 23, 2019, 04:48:12 PM »
Quote from: AIR
AFAIK, SB Sockets are TCP only, so I don't think using Sockets there will work since this requires a UDP connection.

 :(

I'll just have to be happy with myip.sb.

Offline AIR

  • BASIC Developer
  • Posts: 932
  • Coder
Re: Retrieve your External IP address
« Reply #18 on: March 23, 2019, 09:15:33 PM »
Quote from: AIR
AFAIK, SB Sockets are TCP only, so I don't think using Sockets there will work since this requires a UDP connection.

 :(

I'll just have to be happy with myip.sb.

Way back around 2002-2004, Peter wrote a SB module called ssockets.  In the old mailing list, someone asked about UDP and Peter said that while this module was TCP only, that it should be fairly simple to modify it to use UDP.

I found the source on one of his old websites, and am looking it over...

AIR.

Offline John

  • Forum Support / SB Dev
  • Posts: 3597
    • ScriptBasic Open Source Project
Re: Retrieve your External IP address
« Reply #19 on: March 23, 2019, 09:28:39 PM »
Your memory is outstanding!

What I like about SB is I feel I only scratched the surface of it's feature set and there is still much to learn.

Peter mentioned on Twitter that the development Cycle for SB was 1997 to 2006.
« Last Edit: March 23, 2019, 09:46:22 PM by John »

Offline jalih

  • Advocate
  • Posts: 111
Re: Retrieve your External IP address
« Reply #20 on: March 25, 2019, 08:09:54 AM »
Couple of notes:

I hand-crafted the binary query/request that is sent to the dns server.  The alternative would have required the use of the "structs" or "binascii" modules.

AFAIK, SB Sockets are TCP only, so I don't think using Sockets there will work since this requires a UDP connection.

This works under macOS, Linux, and RasPi at this point.

AIR.

Here is updated 8th code that also checks RCODE for errors. Using pack and unpack words makes it really easy to handle buffer of message data.

Code: [Select]


net:INET4 net:DGRAM net:socket var, socket

[ 0xaa, 0xaa, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  "myip", "opendns", "com", 0x00, 0x00, 0x01, 0x00, 0x01 ] "12b1s1c1s1c1s1c5b" pack var, message


: address-info  \  -- ai
  "resolver1.opendns.com" 53 net:getaddrinfo ;


: app:main
  address-info null? if
    drop
    "Server address information lookup failed." . cr
    bye
  then

  socket @ swap message @ 0 net:sendto null? if
    drop
    "Error sending message." . cr
    net:close
    bye
  else
    drop
  then

  512 b:new 0 net:recvfrom null? if
    drop
    "No response from the server" . cr
    net:close
    bye
  then

  \ Test RCODE
  over 3 b:@ nip 0xf n:band not if
    \ Last four bytes from the response are the IP address.
    dup 4 n:- swap b:slice "4:1B" unpack drop
    ' >s a:map
    "." a:join
    "External IP: " . . cr
  else
    2drop
    "Error communicating with the server." . cr
  then
  drop
  net:close
  bye ;

Offline John

  • Forum Support / SB Dev
  • Posts: 3597
    • ScriptBasic Open Source Project
Re: Retrieve your External IP address
« Reply #21 on: March 25, 2019, 08:53:44 AM »
SB also supports binary pack/unpack. Just no UDP.  :-\

Offline AIR

  • BASIC Developer
  • Posts: 932
  • Coder
Re: Retrieve your External IP address
« Reply #22 on: March 29, 2019, 01:22:18 AM »
I created a custom SB module to try this.

Code: ScriptBasic
  1. include ip.bas
  2.  
  3. print "Public IP: " & IP::Public() & "\n"
  4.  
  5. print "Local IP: " & IP::Local("eth0") & "\n"
  6.  
  7. print "MAC Address for eth0: " & IP::MacAddress("eth0") & "\n"

OUTPUT:
riveraa@dpi:~/sb $ sb iptest.sb
Public IP: 24.188.233.50 <--not my real ip.  LOL.
Local IP: 192.168.1.64
MAC Address for eth0: b8:27:eb:2a:e9:22


All done in code, no calls to external web sites (which wouldn't be able to grab the MAC Address.  I hope!), or executing shell commands.

I used libresolv for the DNS Query, and SOCKET & IOCTL calls to get the local IP and MAC Address of the adapter.

I took a slightly different approach to putting the module together; I wrote the core code in pure C and then called the Functions from within the module after compiling the C file along with the interface.c file (similar to what I did with the JSON and SLRE modules).

This is a much cleaner approach since I didn't have to re-write the core code to work within the BES macro system.  All I had to do was plug in the Function calls and I was done.

Coded start to finish on my RasPi.  8)

I'll push this up later today after some cleanup and sleep, it's 4:20am where I am right now!

AIR.

Offline John

  • Forum Support / SB Dev
  • Posts: 3597
    • ScriptBasic Open Source Project
Re: Retrieve your External IP address
« Reply #23 on: March 29, 2019, 07:53:30 AM »
Quote
it's 4:20am

Here on the west coast 4:20 isn't about bedtime.  ;)

I have yet to find a language with an easier to use extension interface.

Looking forward to see your new extension module.
« Last Edit: March 29, 2019, 09:28:39 AM by John »

Offline AIR

  • BASIC Developer
  • Posts: 932
  • Coder
Re: Retrieve your External IP address
« Reply #24 on: August 14, 2022, 03:17:59 PM »
I've been learning the V Programming Language, and tried my hand at this challenge with it:

Code: Go
  1. import net
  2.  
  3. fn main() {
  4.     mut buf := []u8{len: 100}
  5.     mut result := []string{}
  6.    
  7.     mut conn := net.dial_udp('resolver1.opendns.com:53')?
  8.     defer {
  9.         conn.close() or {}
  10.     }
  11.    
  12.     prefix := "\x41\x41\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00"
  13.     message := "\x04\x6d\x79\x69\x70\x07\x6f\x70\x65\x6e\x64\x6e\x73\x03\x63\x6f\x6d"
  14.     suffix := "\x00\x00\x01\x00\x01"
  15.    
  16.     query := prefix + message + suffix
  17.  
  18.     conn.write_string(query) or {
  19.         println(err)
  20.         exit(-1)
  21.     }
  22.     res, _ := conn.read(mut buf)?
  23.  
  24.     for item in buf[res-4..res] {
  25.         result << "$item"
  26.     }
  27.    
  28.     ip := result.join('.')
  29.    
  30.     println("External IP: $ip")
  31.  
  32. }
  33.  

AIR.