IP addresses have been a hot topic lately, for whatever reason. According to my webserver stats, I’m getting plenty of hits on one of my scripts from search engines with terms like “get ip address” and “vb external ip”. Yesterday, Barry talked about a guy wanting to know how to get the IP address of visitors. So to make all of the wanna-be script kiddies out there happy, I’ll mention my favourite way to get IP addresses from a client application. Some of this came in handy when I wrote some stuff to hack a Russian software pirate, but I’ll save that story for another day.
Getting an internal IP address is a snap. All operating systems have a way to view the currently assigned IP address on a network adapter. ‘ipconfig’ in Windows XP and ‘ifconfig’ in UNIX are basically the same command-line interface utilities. With each, you can also redirect the output of these commands to a text file for later parsing. Take a peek at this VBScript that I wrote to grab my NIC‘s IP address, save it to a temporary file on disk and then parse my IP out of it:
' Purpose: Retrieve the currently assigned internal IP address ' I: (none) ' O: IP address Function GetInternalIP() Const DEF_ADDRESS_TEXT = "Address" Const DEF_9X_CMDLINE = "winipcfg /batch" Const DEF_NT_CMDLINE = "%comspec% /c ipconfig >" Dim objWSHShell Dim objFSO Dim strTempFile Dim strTempLine Dim strIP ' create the WSH object Set objWSHShell = CreateObject("WScript.Shell") ' create the FSO object Set objFSO = CreateObject("Scripting.FileSystemObject") ' assemble path to temp file in Windows' TEMP dir strTempFile = objFSO.GetSpecialFolder(2) & "\ip.txt" If (objWSHShell.Environment("SYSTEM")("OS") = "") Then ' Win9x/ME objWSHShell.Run DEF_9X_CMDLINE & " " & strTempFile, _ 0, True Else ' WinNT4/2000/XP/2003 objWSHShell.Run DEF_NT_CMDLINE & " " & strTempFile, _ 0, True End If ' open the temp file With objFSO.GetFile(strTempFile).OpenAsTextStream Do While NOT .AtEndOfStream ' read a line from our temp file strTempLine = .ReadLine If (InStr(strTempLine, DEF_ADDRESS_TEXT) <> 0) Then ' strip out the IP address strIP = Trim(Mid(strTempLine, _ InStr(strTempLine, ":") + 1)) End If Loop ' close the temp file .Close End With ' return the IP address GetInternalIP = strIP ' delete our temp file objFSO.GetFile(strTempFile).Delete ' cleanup Set objFSO = Nothing Set objWSHShell = Nothing End Function |
It could be even simpler using the WMI Win32_NetworkAdapterSetting class, which would negate the need to run system-level commands and parse the output in a text file. In the case that WMI is not installed or you’re on a non-Windows computer and want something slicker, here’s how I do it in Python:
import socket # Purpose: Retrieve the currently assigned internal IP address # I: (none) # O: IP address def GetInternalIP(): strIP = socket.gethostbyname(socket.gethostname()) return strIP |
Pretty simple, but for those folks behind a router using NAT (the main benefit of using a router in the first place), this isn’t your IP address on the Internet; it’s only your internal LAN IP address. The router will be assigned an “external” IP address from your ISP. But you can’t run DOS or UNIX shell commands on commercial routers, and that’s where a few websites come in handy. At the most basic level, these websites merely displaying the IP address that you are assigned to you by your ISP that makes the TCP protocol work over the big network we call the Internet. It does so by displaying the contents of an environment variable, called REMOTE_ADDR, that all webserver software stores for each visiting session. I like CheckIP (from DynDNS) but IP Chicken and ShowMyIP work fine as well. ShowMyIP is especially nice because it displays more info and even offers an XML document. Any language worth a damn should provide a way to send HTTP (and then some) requests out to the Web either natively or via external libraries. Here’s how I use CheckIP and a regular expression to retrieve the external IP address in C#:
using System;
using System.Net;
using System.Web;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
// Purpose: Get the external IP address of the computer. Using
// dyndns.org's checkip tool. This will work
// behind NAT routers.
// I: (none)
// O: external IP address
public string GetExternalIP()
{
const string IP_URL = "http://checkip.dyndns.org";
string strHTML, strIP;
// Send the request and hopefully we'll get response.
// Try to parse out the IP address from the returned HTML
try
{
WebRequest objWebReq = WebRequest.Create(IP_URL);
WebResponse objWebResp = objWebReq.GetResponse();
Stream strmResp = objWebResp.GetResponseStream();
StreamReader srResp = new StreamReader(strmResp,
Encoding.UTF8);
strHTML = srResp.ReadToEnd();
Regex regexIP = new Regex(
@"\\b\\d{1,3}\.\\d{1,3}\.\\d{1,3}\.\\d{1,3}\\b");
strIP = regexIP.Match(strHTML).Value;
return strIP;
}
catch(Exception ex)
{
Console.WriteLine("Can't retrieve external IP: " +
ex.Message);
return null;
}
}
There you go. Now all those folks who have been getting to my site via “get router ip” type Google queries will have a nice blog post describing what they’re looking for instead of simply copying some of my source code. Use it for good and never for evil 😉
19 Responses to "i p freely"
Somedays I wonder if we should be spending our time trying to feed the children of africa than wondering how to get an IP from the client side…
That would be a different blog entry entirely, as opposed to ones about computers, music or living in the “docuverse” or whatever.
Actually, that was an entry of mine back in July.
This is the code for VB.Net!
But i get an error in first line saying Statement is not valid in a namespace.
Any help is appreciated!
VB syntax is somewhat different from C# in terms of declaring/initialising variables like constants and objects. Something like the following should do the trick:
Hope that helps 😀
i still get error: Function GetExternalIP() As String
Statement is not valid in a namespace.
Any idea bro? Have u tried the code to vb.net ? Could you have it a look please?
Or maybe its me ? I have something else to do that i didnt ?
I’ve just compiled the following console app using Visual Studio .NET 2003 with no problems:
worked it fine 🙂 great code man
Could u re-write the code to use a backup url ? In case one is down it can use second or third one to get the ip!
Isnt that good way?
Also you could use the router knowing username and password from it and get the WAN IP!
Lemme know bro
It would be easy to modify the function to use other sites like IP Chicken. The regex that I use would also pick up the IP returned by IP Chicken or any other site that will display your IP Address as text and not as an image. You could either do it as separate function or implement it in the existing one. That’s one of the reasons why I posted my code in the first place…so people can learn from it and expand upon it 😉
Great. I ve modified everything so far but i came up with a little problem. When my internet connection is not active my application sometimes work and sometimes stuck. I get the exception to return me a message to a textbox saying “There is no active connection”. Any ideas y it stucks?
I am calling it from the main form Dim x As New Class1 : x.GetWanIP()
Is there some other way of returning the exception without application freezing? Or somehow to test if internet is available and if its not return the message?
Thanks
nowayout
You shouldn’t really need to explicitly state this unless you really want/need to, but how about if you use WebRequest’s Timout property? If the timeout value (in milliseconds) is reached before the GetResponse() method returns anything (Ex: website down, Internet connection has gone wonky, DNS hiccup, etc), it’ll throw a WebException but we’re already trapping that by using the System.Exception supertype:
I’m not sure why your app locks up, though. I’m wondering what else is going on. What happens if you test out the class and the GetWanIP() method from a simple form like this:
Class1.vb
Form1.vb
Works for me.
Excellent work. Works in 2005 too.
Thanks for letting me know that all is well with VS.NET 2005 🙂
I’m still running VS.NET 2003 on .NET 1.1 and haven’t had the opportunity to use .NET 2.0 yet 🙁
well it is huge.
I am starting school next semester. I enrolled in Java, C++ and COBOL. Do you think i am crazy? 🙂
Not at all. Well, maybe the COBOL class will be a tad crazy 😉
COBOL. I never thought I would have to learn this. It was suppose to have died. Every where I go though they want hteir programmers to know this language.
Any idea how you could create a socket connection between two computers behind NATs in C#???
Carmen
Depending on your application’s goals, you’d need to create server and client components for your project. System.Net.Sockets has everything that you need. If both NAT routers have the same holes poked in them, let’s say TCP 6299, then your server and client and components should do all communication over that port:
server.cs
client.cs
If the ports aren’t known beforehand, I suppose you could always have the client send a special hash to a range of ports that only the indended server will repspond to. So when the client gets the expected response, it should store which port it was on – esentially, an ad-hoc port scanner.
The reason they want you to know COBOL is because there are TONS of legacy apps waiting to be migrated to alternative technology right now…