UPnP : Ouvrir et fermer un port

    Publicités

Users Who Are Viewing This Thread (Total: 0, Members: 0, Guests: 0)

Evaelis

La Voix de la Sagesse
V
Ancien staff
Apr 28, 2010
22,949
468
1,699
Valhalla
Salut, aujourd'hui je vais vous montrer comment ouvrir des ports sur votre box à condition qu'elle soit compatible UPnP (Universal Plug & Play)

Pour commencer, à quoi sert l'UPnP ?
L'UPnP permet à un programme tiers tel qu'un jeux d'ouvrir un port sur votre box sur lequel il pourras dialoguer. Certains programmes tel que skype vous proposes de choisir ce port.
Vous pouvez visionner les ports ouverts dynamiquement sur votre page d'administration (192.168.x.x).
1377429558-ports.png

Tutoriel :
Pour commencer veuillez créer un projet et ajouter une classe avec pour code :
Code:
Imports System.Runtime.InteropServices
Imports System.Net.Sockets
Public Class UPnP
    Implements IDisposable

    Private upnpnat As NATUPNPLib.UPnPNAT
    Private staticMapping As NATUPNPLib.IStaticPortMappingCollection
    Private dynamicMapping As NATUPNPLib.IDynamicPortMappingCollection

    Private staticEnabled As Boolean = True
    Private dynamicEnabled As Boolean = True

    ''' <summary>
    ''' The different supported protocols
    ''' </summary>
    ''' <remarks></remarks>
    Public Enum Protocol

        ''' <summary>
        ''' Transmission Control Protocol
        ''' </summary>
        ''' <remarks></remarks>
        TCP

        ''' <summary>
        ''' User Datagram Protocol
        ''' </summary>
        ''' <remarks></remarks>
        UDP

    End Enum

    ''' <summary>
    ''' Returns if UPnP is enabled.
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public ReadOnly Property UPnPEnabled As Boolean
        Get
            Return staticEnabled = True OrElse dynamicEnabled = True
        End Get
    End Property

    ''' <summary>
    ''' The UPnP Managed Class
    ''' </summary>
    ''' <remarks></remarks>
    Public Sub New()

        'Create the new NAT Class
        upnpnat = New NATUPNPLib.UPnPNAT

        'generate the static mappings
        Me.GetStaticMappings()
        Me.GetDynamicMappings()

    End Sub

    ''' <summary>
    ''' Returns all static port mappings
    ''' </summary>
    ''' <remarks></remarks>
    Private Sub GetStaticMappings()
        Try
            staticMapping = upnpnat.StaticPortMappingCollection()
        Catch ex As NotImplementedException
            staticEnabled = False
        End Try
    End Sub

    ''' <summary>
    ''' Returns all dynamic port mappings
    ''' </summary>
    ''' <remarks></remarks>
    Private Sub GetDynamicMappings()
        Try
            dynamicMapping = upnpnat.DynamicPortMappingCollection()
        Catch ex As NotImplementedException
            dynamicEnabled = False
        End Try
    End Sub

    ''' <summary>
    ''' Adds a port mapping to the UPnP enabled device.
    ''' </summary>
    ''' <param name="localIP">The local IP address to map to.</param>
    ''' <param name="Port">The port to forward.</param>
    ''' <param name="prot">The protocol of the port [TCP/UDP]</param>
    ''' <param name="desc">A small description of the port.</param>
    ''' <exception cref="ApplicationException">This exception is thrown when UPnP is disabled.</exception>
    ''' <exception cref="ObjectDisposedException">This exception is thrown when this class has been disposed.</exception>
    ''' <exception cref="ArgumentException">This exception is thrown when any of the supplied arguments are invalid.</exception>
    ''' <remarks></remarks>
    Public Sub Add(ByVal localIP As String, ByVal Port As Integer, ByVal prot As Protocol, ByVal desc As String)

        ' Begin utilizing
        If Exists(Port, prot) Then Throw New ArgumentException("This mapping already exists!", "Port;prot")

        ' Check
        If Not IsPrivateIP(localIP) Then Throw New ArgumentException("This is not a local IP address!", "localIP")

        ' Final check!
        If Not staticEnabled Then Throw New ApplicationException("UPnP is not enabled, or there was an error with UPnP Initialization.")

        ' Okay, continue on
        staticMapping.Add(Port, prot.ToString(), Port, localIP, True, desc)

    End Sub

    ''' <summary>
    ''' Removes a port mapping from the UPnP enabled device.
    ''' </summary>
    ''' <param name="Port">The port to remove.</param>
    ''' <param name="prot">The protocol of the port [TCP/UDP]</param>
    ''' <exception cref="ApplicationException">This exception is thrown when UPnP is disabled.</exception>
    ''' <exception cref="ObjectDisposedException">This exception is thrown when this class has been disposed.</exception>
    ''' <exception cref="ArgumentException">This exception is thrown when the port [or protocol] is invalid.</exception>
    ''' <remarks></remarks>
    Public Sub Remove(ByVal Port As Integer, ByVal Prot As Protocol)

        ' Begin utilizing
        If Not Exists(Port, Prot) Then Throw New ArgumentException("This mapping doesn't exist!", "Port;prot")

        ' Final check!
        If Not staticEnabled Then Throw New ApplicationException("UPnP is not enabled, or there was an error with UPnP Initialization.")

        ' Okay, continue on
        staticMapping.Remove(Port, Prot.ToString)

    End Sub

    ''' <summary>
    ''' Checks to see if a port exists in the mapping.
    ''' </summary>
    ''' <param name="Port">The port to check.</param>
    ''' <param name="prot">The protocol of the port [TCP/UDP]</param>
    ''' <exception cref="ApplicationException">This exception is thrown when UPnP is disabled.</exception>
    ''' <exception cref="ObjectDisposedException">This exception is thrown when this class has been disposed.</exception>
    ''' <exception cref="ArgumentException">This exception is thrown when the port [or protocol] is invalid.</exception>
    ''' <remarks></remarks>
    Public Function Exists(ByVal Port As Integer, ByVal Prot As Protocol) As Boolean

        ' Final check!
        If Not staticEnabled Then Throw New ApplicationException("UPnP is not enabled, or there was an error with UPnP Initialization.")

        ' Begin checking
        For Each mapping As NATUPNPLib.IStaticPortMapping In staticMapping

            ' Compare
            If mapping.ExternalPort.Equals(Port) AndAlso mapping.Protocol.ToString.Equals(Prot.ToString) Then Return True

        Next

        'Nothing!
        Return False

    End Function

    ''' <summary>
    ''' Attempts to locate the local IP address of this computer.
    ''' </summary>
    ''' <returns>String</returns>
    ''' <remarks></remarks>
    Public Shared Function LocalIP() As String
        Dim IPList As System.Net.IPHostEntry = System.Net.Dns.GetHostEntry(System.Net.Dns.GetHostName)
        For Each IPaddress In IPList.AddressList
            If (IPaddress.AddressFamily = AddressFamily.InterNetwork) AndAlso IsPrivateIP(IPaddress.ToString()) Then
                Return IPaddress.ToString
            End If
        Next
        Return String.Empty
    End Function

    ''' <summary>
    ''' Checks to see if an IP address is a local IP address.
    ''' </summary>
    ''' <param name="CheckIP">The IP address to check.</param>
    ''' <returns>Boolean</returns>
    ''' <remarks></remarks>
    Private Shared Function IsPrivateIP(ByVal CheckIP As String) As Boolean
        Dim Quad1, Quad2 As Integer

        Quad1 = CInt(CheckIP.Substring(0, CheckIP.IndexOf(".")))
        Quad2 = CInt(CheckIP.Substring(CheckIP.IndexOf(".") + 1).Substring(0, CheckIP.IndexOf(".")))
        Select Case Quad1
            Case 10
                Return True
            Case 172
                If Quad2 >= 16 And Quad2 <= 31 Then Return True
            Case 192
                If Quad2 = 168 Then Return True
        End Select
        Return False
    End Function

    ''' <summary>
    ''' Disposes of the UPnP class
    ''' </summary>
    ''' <param name="disposing">True or False makes no difference.</param>
    ''' <remarks></remarks>
    Protected Overridable Sub Dispose(disposing As Boolean)
        Marshal.ReleaseComObject(staticMapping)
        Marshal.ReleaseComObject(dynamicMapping)
        Marshal.ReleaseComObject(upnpnat)
    End Sub

    ''' <summary>
    ''' Dispose!
    ''' </summary>
    ''' <remarks></remarks>
    Public Sub Dispose() Implements IDisposable.Dispose
        Dispose(True)
        GC.SuppressFinalize(Me)
    End Sub

    ''' <summary>
    ''' Prints out some debugging information to use.
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function Print() As List(Of String)

        ' Return list
        Dim L As New List(Of String)

        ' Loop through all the data after a check
        If staticEnabled Then
            For Each mapping As NATUPNPLib.IStaticPortMapping In staticMapping

                ' Add some initial data
                L.Add("--------------------------------------")

                'Grab the rest
                L.Add(String.Format("IP: {0}", mapping.InternalClient))
                L.Add(String.Format("Port: {0}", mapping.InternalPort))
                L.Add(String.Format("Description: {0}", mapping.Description))

            Next
        End If

        'Finisher
        L.Add("--------------------------------------")

        ' Give it back
        Return L

    End Function

End Class
Ou ici : Ce lien n'est pas visible, veuillez vous connecter pour l'afficher. Je m'inscris!

Si vous avez des erreurs, ajoutez les références COM :
NATUPnP 1.0 Type Library
UPnP 1.0 Type Library (Control Point)

Utilisation de la classe :
Pour utiliser la classe, vous devez déclarer un "UPnP" (Il aurait pu trouver un nom comme UPnPClient mais non. Vous pouvez modifier ce nom sur la classe)
Code:
Dim MyUPnPMap As New UPnP
Avant d'ouvrir un port, nous devons vérifier s'il n'est pas déjà ouvert, pour cet exemple, j'utilise un port UDP:

Code:
  If MyUPnPMap.Exists(12345, UPnP.Protocol.UDP) Then
S'il n'existe pas :
Code:
Else
  MyUPnPMap.Add(UPnP.LocalIP, 12345, UPnP.Protocol.UDP, "CG3 Tutoriel")
Ce qui donne un code du style :

Code:
    Function Openport() As Boolean
        Dim MyUPnPMap As New UPnP
        If MyUPnPMap.Exists(12345, UPnP.Protocol.UDP) Then
            Return False
        Else
            MyUPnPMap.Add(UPnP.LocalIP, 12345, UPnP.Protocol.UDP, "CG3 Tutoriel")
            Return True
        End If

    End Function
Vous pouvez tout à fait ajouter un argument port ou protocol à la fonction.
Pour fermer un port c'est le même principe :
Code:
        Dim MyUPnPMap As New UPnP
        MyUPnPMap.Remove(12345, UPnP.Protocol.UDP)
Vous donnez le numéro de port et le protocol.
Code final :
Code:
Public Class Form1

    Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
        If (Open()) Then MsgBox("Win")
    End Sub
    Private Sub Unlog() Handles MyBase.FormClosing
        Dim MyUPnPMap As New UPnP
        MyUPnPMap.Remove(12345, UPnP.Protocol.UDP)
    End Sub
    Function Open() As Boolean
        Dim MyUPnPMap As New UPnP
        If MyUPnPMap.Exists(12345, UPnP.Protocol.UDP) Then
            Return False
        Else
            MyUPnPMap.Add(UPnP.LocalIP, 12345, UPnP.Protocol.UDP, "CG3 Tutoriel")
            Return True
        End If

    End Function
End Class
Je le donne ainsi, car une personne qui ne fait que copier coller ne pourras pas utiliser des sockets.
1377431431-cg3.png

Et voilà nous arrivons au bout de ce tutoriel.
Le code de base n'est pas de moi.
 
Last edited:
M

Membre supprimé 245833

Merci beaucoup, assez bien expliqué, peut-être utile à beaucoup de personne.