In today’s world of cloud computing and distributed systems, networking plays a critical role. One of the most common tasks in networking is to obtain the local outbound IP address of a machine. This can be useful for various reasons, such as identifying your machine on a network, checking for network connectivity, or accessing external services that require your IP address.
In this blog post, we will explore how to get a local outbound IP address in Go application and explain the different methods available.
Local IP address vs Public IP address
Before we start, let’s recap what the difference between a local and public IP address is.
Local IP and Public IP are two types of IP addresses used in computer networking. The main difference between them is their scope of usage and reachability.
A local IP address is used for communication within a local network, such as a home or office network. It is also known as a private IP address and is assigned to a device by a local router. Local IP addresses typically begin with 192.168.x.x
, 172.16.x.x
to 172.31.x.x
, or 10.x.x.x
.
On the other hand, a public IP address is used for communication over the Internet. It is assigned to a device by an Internet Service Provider (ISP) and is unique globally. Public IP addresses are necessary for devices that need to communicate outside of a local network, such as accessing websites or remote servers.
In summary, local IP addresses are used for internal communication within a network, while public IP addresses are used for external communication over the Internet.
In this blog post we are going to show you how to extract the local IP address of your machine.
Get preferred outbound IP address using UDP
The first method of getting the local IP address from within the Go application is to use a UDP (User Datagram Protcol) connection. You need to prepare a UDP connection to any external address, and then from such a connection you can pull the preferred local outbound IP address. Look at the GetLocalIP()
function in the following example:
package main
import (
"fmt"
"log"
"net"
)
func GetLocalIP() net.IP {
conn, err := net.Dial("udp", "8.8.8.8:80")
if err != nil {
log.Fatal(err)
}
defer conn.Close()
localAddress := conn.LocalAddr().(*net.UDPAddr)
return localAddress.IP
}
func main() {
fmt.Println(GetLocalIP())
}
We use the net.Dial()
function from the net
package to prepare a UDP connection to the Google DNS server (8.8.8.8
). The destination address and port does not matter, it may not even exist, the only requirement is that the address be external. Because of how UDP works, the connection is not established anyway - no handshake is performed, no data is sent.
The purpose of this example is to get the local IP address that a UDP connection would use if it were sending data to the destination address. This can be done using the LocalAddr()
method of the connection created. It returns the net.Addr
interface, which can then be casted using type assertion to a specific net.UDPAddr
so that the IP address can be extracted as a net.IP
struct.
Get local IP address by looping through all network interface addresses
Another way to get a local IP address is to iterate through all network interface addresses. They can be retrieved using the net.InterfaceAddrs()
function. Take a look at the example:
package main
import (
"fmt"
"log"
"net"
)
func GetLocalIPs() ([]net.IP, error) {
var ips []net.IP
addresses, err := net.InterfaceAddrs()
if err != nil {
return nil, err
}
for _, addr := range addresses {
if ipnet, ok := addr.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
if ipnet.IP.To4() != nil {
ips = append(ips, ipnet.IP)
}
}
}
return ips, nil
}
func main() {
ips, err := GetLocalIPs()
if err != nil {
log.Fatal(err)
}
fmt.Println(ips)
}
We cast all addresses to the net.IPNet
struct, then filter out Loopback addresses and take only IPv4 IPs to the resulting list. This method extracts all local addresses, so if your machine has more than one local IP assigned, then the resulting slice will have more than one element.