Question 198

Comment connaître son adresse IP publique ?

Préambule

L'adresse IP (Internet Protocol) est une série de 4 numéros de 8 bits chacun séparé par un point sous la forme « A.B.C.D » où chaque numéro est un entier de 0 à 255 (exemple : 24.200.243.189). Lorsque nous parlons d'adresse IP publique nous parlons de l'adresse IP qui vous identifie sur la toile Internet. Nous vous invitons à lire l'article à la page suivante si vous n'êtes pas initiés à toutes ses bases : http://fr.wikipedia.org/wiki/Adresse_ip

Brièvement, si vous n'avez qu'un ordinateur avec un simple modem, vous pourrez trouver facilement votre adresse IP publique à l'aide de la commande ipconfig. L'adresse IP publique peut être statique (elle ne changera alors jamais) ou dynamique (alloué par un serveur DHCP à chaque reconnexion la plupart du temps). En revanche, si vous possédez un routeur ou certains autres types d'appareils en amont, vous ne pourrez pas voir facilement votre adresse IP publique car il y a le NAT (http://fr.wikipedia.org/wiki/Network_address_translation). Dans ce cas précis, la commande ipconfig vous affichera une adresse IP dite locale. L'IANA (http://fr.wikipedia.org/wiki/Internet_Assigned_Numbers_Authority) a défini 3 espaces d'adresses privées. Si vous êtes un particulier, votre adresse IP locale sera du type 192.168.0.x mais il se peut que vous rencontriez des adresses de la forme 10.0.0.x ou 172.16.0.x. Il existe également d'autres cas particulier comme les adresses APIPA (http://fr.wikipedia.org/wiki/APIPA).

On voit donc qu'un grand nombre de facteurs peuvent intervenir, qui peuvent rendre compliquée la détermination de l'adresse IP publique.

Comment faire ?

La méthode présentée ici utilise le fait qu'un serveur connait l'adresse d'un client qui s'y connecte, par exemple pour demander une page web. Il peut donc écrire l'adresse du client en question dans la page qu'il fournit en réponse.

Il suffit donc de se connecter à une page Web affichant l'adresse IP publique, de récupérer le contenu de la page puis finalement d'extraire l'adresse IP qui a été écrite sur la page.

En pratique, c'est très simple, il existe de nombreuses pages Web offrant ce service. L'exemple présenté ici utilise la page suivante : http://www.myip.dk/. Il va de soi que cette méthode, qui implique un parsing de la page retournée, est très dépendante de la page elle-même. On veillera donc à choisir une page dont on est sûr de la validité dans le temps ; c'est notamment le cas de la page proposée ci-avant.

Le contenu de la page est récupérée par la classique fonction UrlDownloadToFile. L'inconvénient est de passer par un fichier, l'avantage est d'être une simple API, ne nécessitant pas d'ajouter un composant (type Inet ou MsWinsock).

La fonction GetPublicIP retourne l'IP publique. Elle utilise quelques fonctions intermédiaires pour le traitement des buffers et des fichiers.

Option Explicit

'
' API permettant de récupérer le contenu d'une page Web dans un fichier
'
Private Declare Function URLDownloadToFile Lib "urlmon" Alias "URLDownloadToFileA" (ByVal pCaller As Long, ByVal szUrl As String, ByVal szFileName As String, ByVal dwReserved As Long, ByVal lpfnCB As Long) As Long

'
' Lit le contenu d'un fichier et retourne un buffer
'
Public Function readFromFile(ByVal szFileName As String, ByRef buf As String) As Boolean
    Dim f As Integer

    On Error GoTo readFromFile_err

    f = FreeFile
    Open szFileName For Binary As #f
        buf = Space$(LOF(f))
        Get #f, , buf
    Close #f
    readFromFile = True
    
readFromFile_ok:
    Exit Function
readFromFile_err:
    Resume readFromFile_ok
End Function

'
' Appelle URLDownloadToFile et stocke le résultat dans un fichier
'
Function DownloadPage(ByVal url As String, ByVal FileName As String) As Boolean
    Dim done As Boolean
    Dim value As Long

    On Error Resume Next
    
    done = True
    If Dir$(FileName) <> "" Then
        Kill FileName
    End If
    value = URLDownloadToFile(0, url, FileName, 0, 0)
    If Dir$(FileName) = "" Then
        done = False
    End If
    DownloadPage = done
End Function

'
' Retourne le contenu d'une page Web dans une chaine de caractères
'
Public Function getHtmlFromUrl(ByVal szUrl As String, ByRef szBuf As String) As Boolean
    Dim ret As Boolean

    ret = DownloadPage(szUrl, App.Path & "\my_temp_ip.dat")
    If ret Then
        ret = readFromFile(App.Path & "\my_temp_ip.dat", szBuf)
    End If
    getHtmlFromUrl = ret
End Function

'
' Retourne l'adresse IP publique
'
Public Function GetPublicIP(ByRef szIP) As Boolean

    Dim szBuf As String
    Dim p As Long
    Dim ret As Boolean

    ret = getHtmlFromUrl("http://www.myip.dk/", szBuf)
    If ret Then
        p = InStr(szBuf, "<title>")
        If p > 0 Then
            p = InStr(p, szBuf, ":")
            If p > 0 Then
                szIP = Trim$(Mid$(szBuf, p + 1, InStr(p, szBuf, "</title>") - p - 1))
                GetPublicIP = True
            End If
        End If
    End If
    
End Function

'
' Exemple d'utilisation de GetPublicIP
'
Private Sub Command1_Click()
Dim ip As String
Dim ret As Boolean

    ret = GetPublicIP(ip)
    If ret Then
        MsgBox "Votre IP publique est : " & ip
    Else
        MsgBox "impossible de lire l'adresse IP"
    End If
End Sub

On peut bien sûr utiliser n'importe quelle page Web qui écrit l'adresse IP publique. Dans ce cas, il suffit de modifier le parsing rudimentaire effectuée dans la fonction GetPublicIP pour extraire l'adresse IP affichée. Comme on l'a dit, on essaiera d'utiliser une page dont on est sûr qu'elle aura une longue validité dans le temps.

L'implémentation donnée ici ne constitue qu'un exemple. Sur base de cette idée, il est possible de réaliser des implémentations différentes. Par exemple, rien n'interdit d'écrire une fonction qui connaît plusieurs adresses et plusieurs formats : en cas d'échec avec l'une des pages, on cascadera sur la ou les suivantes.

Pour aller plus loin

Voir aussi :

Date de publication : 11 septembre 2008
Dernière modification : 11 septembre 2008
Rubriques : Internet & mails, Réseaux
Mots-clés : IP, adresse, publique, connaitre, récupérer, récupéré, internet, local, réseau