Consider the following setup:
A windows PC with a LAN interface and a WiFi interface (the standard for any new laptop). Each of the interfaces might be connected or disconnected from a network. I need a way to determine which one of the adapters is the one connected to the internet - specifically, in case they are both connected to different networks, one with connection to the internet and one without.
My current solution involves using IPHelper's "GetBestInterface" function and supplying it with the IP address "0.0.0.0".
Do you have any other solutions you might suggest to this problem?
Following some of the answers, let me elaborate:
I need this because I have a product that has to choose which adapter to bind to. I have no way of controlling the setup of the network or the host where the product will run and so I need a solution that is as robust as possible, with as few assumptions as possible.
I need to do this in code, since this is part of a product.
#Chris Upchurch: This makes me dependent on google.com being up (usually not a problem) and on any personal firewall that might be installed to allow pinging.
#Till: Like Steve Moon said, relying on the adapter's address is kind of risky because you make a lot of assumptions on the internal network setup.
#Steve Moon: Looking at the routing table sounds like a good idea, but instead of applying the routing logic myself, I am trying to use "GetBestInterface" as described above. I believe what it should do is exactly what you outlined in your answer, but I am not really sure. The reason I'm reluctant to implement my own "routing logic" is that there's a better chance that I'll get it wrong than if I use a library/API written and tested by more "hard-core" network people.
Technically, there is no "connected to the Internet". The real question is, which interface is routeable to a desired address. Right now, you're querying for the "default route" - the one that applies if no specific route to destination exists. But, you're ignoring any specific routes.
Fortunately, for 99.9% of home users, that'll do the trick. They're not likely to have much of a routing table, and GetBestInterface will automatically prefer wired over wireless - so you should be good. Throw in an override option for the .1% of cases you screw up, and call it a day.
But, for corporate use, you should be using GetBestInterface for a specific destination - otherwise, you'll have issues if someone is on the same LAN as your destination (which means you should take the "internal" interface, not the "external") or has a specific route to your destination (my internal network could peer with your destination's network, for instance).
Then again, I'm not sure what you plan to do with this adapter "connected to the Internet", so it might not be a big deal.
Apparently, in Vista there are new interfaces that enable querying for internet connectivity and more. Take a look at the NLM Interfaces and specifically at INetworkConnection - you can specifically query if the network connection has internet connectivity using the GetConnectivity method.
See also: Network Awareness on Windows Vista
Unfortunately, this is only available on Vista, so for XP I'd have to keep my original heuristic.
I'd look at the routing table. Whichever NIC has an 0.0.0.0 route AND is enabled AND has the lowest metric, is the nic that's currently sending packets to the internet.
So in my case, the top one is the 'internet nic'.
IPv4 Route Table
===========================================================================
Active Routes:
Network Destination Netmask Gateway Interface Metric
0.0.0.0 0.0.0.0 10.0.0.10 10.0.0.51 20
0.0.0.0 0.0.0.0 10.0.0.10 10.0.0.50 25
(much other stuff deleted)
Another alternative is to ping or GetBestInterface 4.2.2.2 - this is an old and venerable DNS server, currently held by GTEI; formerly by Sprint if I remember right.
Start > Run > cmd.exe (this works in XP and Vista): ipconfig /all
This displays all info about the interfaces in your computer. The "public" facing interface should have a public IP address. For starters, it should not be 192.168.x.x or 10.x.x.x :)
running traceroute to some public site will show you. Of course, there may be more than one interface that would get you there.
Look at the routing table? Generally, unless you're routing between the networks in windows (which is possible, but unusual for a client computer these days) the interface that holds the default route is going to have the Internet connection.
Your question didn't detail why or what you're doing this with so I can't provide any specifics. The command line tool "route" may be of some help, but there are probably libraries for whatever programming language you're using to look at the routing table.
You can't rely on the IP address of the interface (e.g., assuming an RFC-1918 address [192.168.0.0/16, 172.16.0.0/12, 10.0.0.0/8] isn't the internet) since most sites have some kind of NATed firewall or proxy setup and the "internet" interface is really on a "private" lan that gets you out to the Internet.
UPDATE: Based on your further information, it sounds like you have a decent solution. I'm not so sure about the choice of 0.0.0.0 since that's a boundary case for IP address -- might be OK on your particular mix of platform/language. Sounds (from the API description) like you could just specify an address, so why not some address known to be on the Internet, e.g. the IP address of your web site, or something more random like 65.66.67.68? Just make sure not to pick one of the rfc-1918 addresses, or the localhost range (127.0.0.0/8), or multicast, any other reserved range, and any address that resolves to a .mil or .gov (while it doesn't sound like getbestinterface sends any traffic, it would suck to find out by having the feds break your door down... :)
Looking at the network point of view, either could be routing to the "internet" at any time. If things like spanning tree protocol are enabled on a switch then you may find that what may have been the routing card to begin with may not be anymore.
Ping google.com though each NIC.
Related
As the question states, I have two ethernet devices I need to use. A wifi hotspot for general traffic as well as a LAN connection for local traffic (192.168.1.*). Right now the wifi receives all traffic and disregards the existence of my local LAN devices. I am trying to communicate with this device using python's urllib2 and basic http fetches. The program works partially when I turn one or the other off (turning wifi off makes the LAN code work, and turning LAN off makes wifi/general traffic code work). I believe this is more of an operating system issue than a programming question, but I might be mistaken. I have been messing with the Ethernet setting in system preferences, but nothing has been working so far.
Thanks for the help.
Depending on your needs and degrees of freedom, you can:
1) Easiest: If you can control one or both network ranges, you can put wifi and LAN on different subnets. For example, 192.168.2.* could be LAN traffic, and 192.168.1.* could be wifi. If only the WiFi side has a gateway, then all traffic except 2.* traffic should route through WiFi, and all 1.* traffic goes to the LAN. No change to your computer.
2) Medium: if you don't control the networks, you can define routing rules for the two ports. This lets you say certain IP addresses should be reached thru wifi, vs others thru LAN port. An example in Linux, which I think should work on OS X too: http://linux-ip.net/html/routing-tables.html The trickiest thing is to make sure you won't get in the way when you're in someone else's network. You can do this by creating narrow routing rules, or turning them off when you don't need them. It sounds like you're doing this from a python program, so maybe the program could turn this on and off at start and finish.
3) Slightly more exotic: I wasn't totally sure from your question, but if you're trying to do load balancing (not separate networks), you could create rules to bond together two network ports and spread traffic across them. This isn't something I've done, but real network engineers know how to set this stuff up.
I could expand on one of these if you clarify what you're trying to do and what degrees of freedom you have.
For somebody don't want to do the study you can simply repeat my steps:
Open system preferences
click on Network
(ensure the precedence, first thunderbolt then wifi) click on thunderbolt
Configure IPv4 choose manually
delete router
done!
I have exactly the same user case. But I read this without any network knowledge.
I achieved this by simply following #Nils' 1) instructions. I only understand theses instructions after reading this link
I wrote a tool running on a system (Win7) with two network interfaces, each linked to a different subnet, each with its own gateway which is then linked to two separate distant networks (there are outgoing firewalls after each gateway). I’m initiating outgoing TCP connections via both NICs by using Socket.Bind (before doing Connect) to each relevant NIC’s IP address. First NIC is working fine, but for the second NIC, I’m getting SocketException: “A socket operation was attempted to an unreachable network”.
My original understanding was that since sockets are bound to concrete NIC’s local endpoint, which has its gateway defined, the connection should be routed to this gateway and therefore should work. However, it seems that source IP address is ignored and the routing is working according to local routing table (i.e. second NIC’s connect request goes to first, default, network and being rejected because it has wrong subnet).
Adjusting local routing tables helps, but it makes me wonder about the whole reasoning behind ability of the socket to bind to specific local IP.
Doing some extra reading, I found out that, indeed, there’s such thing as “source IP routing”, but it is disabled in Windows by default (via DisableIPSourceRouting registry setting), due to security reasons, as described, e.g. here:
http://msdn.microsoft.com/en-us/library/ff648853.aspx
http://www.bloggersbase.com/disableipsourcerouting/
Questions:
If my original understanding was correct (i.e. Socket.Bind should be enough) – why it is not working without modifying routing tables?
If my understand was NOT correct (i.e. Socket.Bind is ignored and routing is used) – what’s the point of having Socket.Bind? Why doing it at all?
Also, I’d like to understand better, what is the actual risk of having source IP routing enabled (preferably with example of a possible exploit)?
Any ideas of solving the requirement without manually modifying local routing table will be greatly appreciated.
Many thanks.
OK, after some reading, here are some high-level explanations on what's happening. I still need to verify the below conclusions in my system. Apparently, local binding is typically ignored when selecting network interface. Instead, routing table is used for this. However, in Strong Host Model (default for Vista and newer, non-existant in XP), source IP is used as a 'constraint' in the routing table lookup.
Brief explanation about strong host model vs. weak host model:
http://technet.microsoft.com/en-us/magazine/2007.09.cableguy.aspx
Explanation on what's different in XP vs newer Windows versions in respect to the above:
http://blogs.technet.com/b/networking/archive/2009/04/24/source-ip-address-selection-on-a-multi-homed-windows-computer.aspx
First off, you guys are all really helpful - thank you a lot!
Is there a way to figure out what type of network a Mac is connected to? WiFi? Cable? USB Modem? Any Cocoa / Foundation framework I can use to figure that out?
Thank you,
Matthias
You can tell whether the Mac is using WiFi, whether it is using a modem, and whether it is using hard Ethernet (which could be cable, DSL, or something else). Note that these are not mutually exclusive, there may be multiple connections of a single type (I have two Ethernet ports, for example), and that being connected to an IP network does not necessarily mean connection to the Internet.
You'll probably find the System Configuration API helpful. See also the framework reference.
You may also want to look at the source for HardwareGrowler in the Extras folder of the Growl source code.
You could ask for the route table and see what the default route is, that would tell you to some degree of accuracy what the active connection is.
This obviously has a lot to do with how you define 'some degree of accuracy'. Generally the main internet connection will also be the default route. I'm assuming you also want active connection to mean 'internet connection'.
netstat -rn
Routing tables
Internet:
Destination Gateway Flags Refs Use Netif Expire
default 192.168.0.1 UGSc 22 14 en1
so for me, my default route goes out the en1 interface. I think you need to be a lot more specific on what you mean by 'active/current' means to you.
CAVEAT: just because my default gw is on en1, does not necessarily mean that's where all my inet traffic goes. (it happens to be true in my case, but don't count on it as truth, but would probably be correct more than half the time).
To help users, I would like my code to discover Oracle databases on the LAN. I thought to do this by first detecting all hosts, then checking each host to see if it is listening on Oracle's default port.
Any ideas how to go about this? Preferably in Java, but any language or algorithm would do.
Are you using DHCP? If so, your DHCP server has a list of the leases it has passed out. That should do you for a list of hosts on the LAN. Then try opening a connection to the Oracle port on each of those hosts and see if it accepts the connection.
It should be pretty simple to implement as a shell script with half a dozen lines or so. Java seems like overkill for something like this. Loop through the leases file, grab the IP from each lease, and telnet to the Oracle port; if it connects, disconnect and print the IP to standard out.
If you want to stay platform-independant, and unless you have access to some kind of database that lists the hosts, the only way to get a list is to try each IP address in the local network - might as well try to connect to the Oracle port on each of them.
There are lots of problems with this approach:
Will only search through the local network, which may only be a small part of the LAN (in case of large companies with lots of subnets)
Can take a long time (you definitely want to reduce the timeout for the connection attempts, but if someone has configured his LAN as a class A network, it will still take forever)
Can trigger all kinds of alerts, such as desktop users' personal firewalls, and intrusion detection systems - because you're doing exactly the same thing someone trying to exploit a security hole in Oracle servers would do
As brazzy points out, scanning for hosts is likely to cause problems, especially if there is a bug in your scanner.
A better approach may be to get the owners of the databases to register them somewhere, for example in a local DNS service (or does Oracle have zeroconf support?), or simply on some intranet webpage or wiki.
You better register the SID names/addresses to some server with a fixed address(maybe with a simple web service), and then query the list from there. Another approach is the bruteforce one (explained by #brazzy) by scanning one or more subnets, but this isn't really a good thing to do.
In case you are looking for a tool Loo#Lan can do this for you. Unfortunately there's no source available...
All of these smart answers are the reasons why many companies do not use the default port. Using a different port for each database is entirely possible, you know.
I often run into problems where I can't get something to connect to something else. I usually forget to check something obvious. Can you help with:
A tip/technique for diagnosing a connection issue
The name of a tool or application that can help (and the situation in which it's useful)
I know the question is a little non-specific, but hopefully the answers can form a useful starting point for anybody who's stuck trying to get computers/programs talking to each other.
Please can you give one answer per answer so the best ones can be voted up.
Simple checks to run when debugging network problems:
Has each machine got an IP address, Go to command prompt and run ipconfig. Key things to check here are the interfaces and ensuring the appropriate ones have IP addresses.
Check both machines IP addresses are in the same range and subnet if you are running it on an internal or Virtual network.
Try pinging each machine from the other to see if they can communicate with each other. Note that some firewalls will block ping requests.
If Pinging fails then check to see if firewalls are active. If the communication is within a 'safe' internal network then try disabling the firewalls and re-pinging.
If the connections are over a wireless network then check signal strength.
If pinging fails and you are connecting through several networks then try running a tracert to see at which will may show you where on the network the connection is failing.
If you are able to ping but not connect then check firewall settings and network connection settings. Windows 2000+ has the capability of setting port an ip access on a connection properties.
Try drawing a network diagram of the connections to help in visualising the problem.
If you are connecting through routers, firewalls and loadbalancers then check that all devices are not tied to any specific ip addresses and that the IP address redirection (if in place) is correct. Also check any NAT logs to see if connections are being received and properly re-directed.
Wireshark
Latest versions of ProcMon
netstat
Wireshark www.wireshark.org
Wireshark is a network protocol analyzer for Unix and Windows.
Features:
Deep inspection of hundreds of protocols, with more being added all the time
Live capture and offline analysis
Standard three-pane packet browser
Multi-platform: Runs on Windows, Linux, OS X, Solaris, FreeBSD, NetBSD, and many others
Captured network data can be browsed via a GUI, or via the TTY-mode TShark utility
The most powerful display filters in the industry
Rich VoIP analysis
Read/write many different capture file formats: tcpdump (libpcap), Catapult DCT2000, Cisco Secure IDS iplog, Microsoft Network Monitor, Network General Sniffer® (compressed and uncompressed), Sniffer® Pro, and NetXray®, Network Instruments Observer, Novell LANalyzer, RADCOM WAN/LAN Analyzer, Shomiti/Finisar Surveyor, Tektronix K12xx, Visual Networks Visual UpTime, WildPackets EtherPeek/TokenPeek/AiroPeek, and many others
Capture files compressed with gzip can be decompressed on the fly
Live data can be read from Ethernet, IEEE 802.11, PPP/HDLC, ATM, Bluetooth, USB, Token Ring, Frame Relay, FDDI, and others (depending on your platfrom)
Decryption support for many protocols, including IPsec, ISAKMP, Kerberos, SNMPv3, SSL/TLS, WEP, and WPA/WPA2
Coloring rules can be applied to the packet list for quick, intuitive analysis
Output can be exported to XML, PostScript®, CSV, or plain text.
work the OSI model from the bottom up
Physical (Do you have a network adapter/connection)
Link layer (arp, ethernet port blocked by network team (I've seen this where locked down environments see two MAC addresses coming from one workstation port and shut down the port)
Network layer (ipconfig, tracert, ping,)
Do you have a network address (DHCP, fixed)
Are you on a proper subnet/have routing between subnets
Is something in the middle blocking you
firewalls, routing tables
When in doubt, check to see if the windows firewall is messing with your communications. 8 times out of 10, it's at fault.
Using tracert is a good start to see how far along the chain you are getting.
For virtual machines it's usally a good idea to make sure you have the loopback adapter set correctly in the Host os.
Most frequently used tool is the ping. It can be used both to test your connection and the availability of a target
Second tool is the tracert if you want to see where the packets get lost.
For more advanced debugging I use the following tools: nmap, wireshark, etc.
Windows has a netstat utility which is pretty similar to the Unix netstat and can do a number of different things that might help you solve network issues.
Random example:
netstat -r displays routing information
netstat /? for usage information
Since you said you're using 2 virtual machines I would hazard a guess that both machines are setup in a NAT configuration (rather than a unique network device) -- In the NAT configuration, neither machine would (typically) be able to ping the other.
If you're familiar with the command line, you can try the "netstat" command.
You can also try "arp -a" to list all the IP/MAC addresses known to your PC.
The "tracert [ip address]" command will show you how many gateways/routers your packets jump through on their way to their destination. (This is probably not helpful if both machines are on the same network, though.)
And don't forget to check your Windows firewall settings.
Otherwise, if you want to get down and dirty, you can try the packet sniffer known as Wireshark: http://www.wireshark.org/ (aka. Ethereal)
Pull the network cable out
If you can get some communications to a device (eg a ping), but can't get your program to talk to a service on the computer. Then, try pulling the network cable out and see if the ping stops. This will verify you're communicating with the computer you really think you are.
On windows i user PortQueryUI : http://www.microsoft.com/en-us/download/details.aspx?id=24009
DNS activity: Portable DNS Cache and Firewall;
General network activity: Wireshark, Network Monitor;
Windows utilities: ping, netstat, nslookup.
You need to be use the process of elimination, for example if you can ping the ip address but not the hostname then there's DNS issues. If you can ping the system but not connect to a share etc.
DNS out of sync
If you're using a virtual machine and you perform a roll-back on it, then it could become out of sync with the DNS (Domain name server). Try to remove and re-add the machine to the domain, or if you've got access to the DNS machine, then get it to flush its cache.