The normal way to find your real external IP address is to use your browser to go to a site such as "WhatsMyIP". I needed to do this programatically without the burden of using HTML. What I came up with is a way to verify a forwarding port within a NAT router, while at the same time discovering your public IP address.
Port forwarding can be somewhat onerous for the casual user, and verifying that it is successful is part of the task. To accomplish this, we run a proxy type server on the other side of the NAT router. You send the port number that you want tested to that outside server, and the outside server tries to establish a TCP connection with your router on that port. If the router is properly configured, it will forward that request to your computer and the router's public IP address that was used to make the initial connection with the server will be sent to you.
Port forwarding usually requires that you use fixed IP addressing on your computer rather than DHCP, although it is sometimes possible to configure a NAT router to assign a fixed IP address using DHCP.
Even with the router properly configured, you can still have problems with your firewall. If you are running the Microsoft Firewall, it will prompt you to allow the outside connection.
Last but not least, most ISPs will block some problematic ports such as port 21(FTP), 25(SMTP), 80(WWW), 110(POP3), 6667(IRCD), 135-139(DCOM/NETBIOS), 443(SSL), 445(MS-DS), and 1433-1434(MS-SQL) on residential connections, and there is nothing you can do about it except use a different port or get a business connection.
If there is sufficient interest, I can later supply a service version of the server software.
Note: Both programs use SimpleSock, which requires operating systems that actively support both IPv4 & IPv6. This more or less restricts them to Windows Vista or better.
Option Explicit
Private Sub Main()
With New WinHttp.WinHttpRequest
.Open "GET", "https://api.ipify.org"
.Send
If .Status = 200 Then
MsgBox .ResponseText
Else
MsgBox .StatusText
End If
End With
End Sub
Seems to work fine. Probably plenty of others out there too, it was just the first hit on a search.
As the name suggests, it was primarily put together as a NAT port forwarding tester. The Public IP was an after thought that took about 2 lines of code. I realize that online port scanners could do the testing, but I needed to do this in code and I wanted to keep it small. It would have been nice to use the UPnP code that you posted, but that didn't work out.
As an aside, I found this bit of code to get the external IP, but it looks like it is for some other kind of Basic and I could not get it to work.
Code:
Imports NATUPNPLib
Public Class RouterInfo
Dim cRouter As NATUPNPLib.UPnPNAT
Public Sub New()
cRouter = New NATUPNPLib.UPnPNAT
End Sub
Public Function GetExternalIP() As String
Dim lMapper = cRouter.StaticPortMappingCollection
Dim lMappedPort As NATUPNPLib.IStaticPortMapping
Dim lExtIP As String
If Not lMapper Is Nothing Then
For Each lMappedPort In lMapper
lExtIP = lMappedPort.ExternalIPAddress().ToString
Exit For
Next
GetExternalIP = lExtIP
Else
GetExternalIP = "<Unable to resolve external IP>"
End If
End Function
Dim cRouter As NATUPNPLib.UPnPNAT
Set cRouter = New NATUPNPLib.UPnPNAT
'Check to make sure NAT UPnP is active
If cRouter.StaticPortMappingCollection Is Nothing Then
Debug.Print "UPnP not Found!"
exit sub
End If
'Find number of mappings
Debug.Print "Mappings = " & cRouter.StaticPortMappingCollection.Count
'Return properties IP of this router.
Debug.Print "Description: " & cRouter.StaticPortMappingCollection(8765, "TCP").Description
Debug.Print "Enabled: " & cRouter.StaticPortMappingCollection(8765, "TCP").Enabled
Debug.Print "ExternalIPAddress: " & cRouter.StaticPortMappingCollection(8765, "TCP").ExternalIPAddress
Debug.Print "ExternalPort: " & cRouter.StaticPortMappingCollection(8765, "TCP").ExternalPort
Debug.Print "InternalClient: " & cRouter.StaticPortMappingCollection(8765, "TCP").InternalClient
Debug.Print "InternalPort: " & cRouter.StaticPortMappingCollection(8765, "TCP").InternalPort
Debug.Print "Protocol: " & cRouter.StaticPortMappingCollection(8765, "TCP").Protocol
This particular router (ActionTec T2200H) does not return the Count, nor will it allow port mappings to be removed. Now if I could only figure out how to assign "cRouter.StaticPortMappingCollection" to a variable.
Now if I could only figure out how to assign "cRouter.StaticPortMappingCollection" to a variable.
Not sure why you'd need to, but since this works fine:
Code:
Dim UPnPNAT As NATUPNPLib.UPnPNAT
Dim StaticPortMapping As NATUPNPLib.IStaticPortMapping
Set UPnPNAT = New NATUPNPLib.UPnPNAT
On Error Resume Next
Set StaticPortMapping = _
UPnPNAT.StaticPortMappingCollection.Add(lngExtPort, _
"UDP", _
lngIntPort, _
Winsock.LocalIP, _
True, _
"Demo Port Mapping")
If Err Then
MsgBox "Add failed, error " & Msg(Err.Number)
Else
On Error GoTo 0
MsgBox "Add succeeded, ExternalIPAddress = " _
& StaticPortMapping.ExternalIPAddress
End If
Maybe:
Code:
Dim UPnPNAT As NATUPNPLib.UPnPNAT
Dim StaticPortMappingCollection As NATUPNPLib.IStaticPortMappingCollection
Set UPnPNAT = New NATUPNPLib.UPnPNAT
Set StaticPortMappingCollection = UPnPNAT.StaticPortMappingCollection