69

I have a Linux server and I want to find the main IPv6 address via one single command line.

My command so far:

$ ip addr show dev eth0 | sed -e's/^.*inet6 \([^ ]*\)\/.*$/\1/;t;d'

which shows:

2001:410:0:39:221:28ff:fe46:eef4
fe80::221:28ff:fe46:eef4

But I want only one occurrence, so that the output reads:

2001:410:0:39:221:28ff:fe46:eef4
K7AAY
  • 9,725

14 Answers14

66
ip -6 addr

will show your IPv6 addresses.

Jim G.
  • 3,390
14

/sbin/ip -6 addr | grep inet6 | awk -F '[ \t]+|/' '{print $3}' | grep -v ^::1 | grep -v ^fe80

The output of /sbin/ip -6 addr | grep inet6 looks something like this:

inet6 ::1/128 scope host 
inet6 2001:123:456:55f::1/64 scope global 
inet6 fe80::62eb:69ff:fed2:d2a6/64 scope link 

awk -F '[ \t]+|/' '{print $3}' splits each line setting delimiters to be either one or more white spaces or a forward slash. The part we need is the $3.

grep -v ^::1 | grep -v ^fe80 to exclude any line starting with ::1 or fe80.

Qian Chen
  • 233
13

To get only the IPv6 addresses you use the ip addr command and filter already with -6 for IPv6 addresses only.

ip -6 addr

If you want to specify a network adapter you might append show dev eth0 while eth0 should be replaced by your network adapter.

ip -6 addr show dev [eth0]

Since you are looking only for the external IP address you should add a scope global.

ip -6 addr show dev [eth0] scope global

finally you pipe this into your sed command.

ip -6 addr show dev [eth0] scope global | sed -e's/^.*inet6 \([^ ]*\)\/.*$/\1/;t;d'
LUXS
  • 231
6
$ /sbin/ifconfig | grep inet6
      inet6 addr: fe80::2ff:19ff:fe60:1a00/64 Scope:Link
      inet6 addr: fe80::211:22ff:fe33:4455/64 Scope:Link
      inet6 addr: ::1/128 Scope:Host

If you want a random selection of one IPv6 address

$ /sbin/ifconfig | grep inet6 | head -n 1
      inet6 addr: fe80::2ff:19ff:fe60:1a00/64 Scope:Link

If you want the IPv6 address of the most common name for the first Ethernet adapter

$ /sbin/ifconfig eth0 | grep inet6
      inet6 addr: fe80::2ff:19ff:fe60:1a00/64 Scope:Link

If you just want the address

$ /sbin/ifconfig eth0 |  awk '/inet6/{print $3}'
fe80::2ff:19ff:fe60:1a00/64
5

I know this is an old question, but no-one has mentioned that ip can produce JSON output which is easy to query:

$ ip -json address list wlo1 | jq -r '.[0].addr_info[] | select(.family=="inet6" and .scope=="global") | .local'
2001::d4ba:c7f9:1133

Avoids all that mucking around with sed/awk/perl/ruby/COBOL/your-text-tool-of-choice. This will always return a global IP6 address if there is one. It's also easy to adapt to other address families and scopes.

Tom
  • 604
4

ip -6 a show

is a good and effective way to show all the IPv6 addresses unfortunately including some that are only use locally (loopback)

so a better alternative is to filter some specific scope ('global', 'dynamic' and 'up') :

ip -o -6 a show scope global dynamic up (one per line)

finally, it can be easily grepable with IPv6 pattern matching

ip -6 a show scope global dynamic up|egrep -o '([0-9a-f:]+:+)+[0-9a-f]+'

...or use the -m 1 grep option to keep only the first match

unfortunately it is not necessarily the main one nor the most used address

Finally, to show only the main/preferred interface used, select the mngtmpaddr scope:

ip -6 addr show scope global dynamic mngtmpaddr up|egrep -o '([0-9a-f:]+:+)+[0-9a-f]+'

2

With a few small tweaks, your original attempt would've worked:

ip -o -6 addr show eth0 | sed -e 's/^.*inet6 \([^ ]\+\).*/\1/'

The big change there is the addition of the -o flag to causes the entries to be printed out, one per line, which make it easier to run sed over them.

2

First, you need to remember that with IPv6 any machine may have several IPv6 addresses, and they may be on separate networks, and any of them might be used, depending on where you want to reach.

So, before you can answer the question of what is your source IP address you have to decide where you're sending the traffic. Then you can just ask Linux to tell you which IPv6 address will be the source when you send traffic to that destination.

If you're sending it to "the Internet" then just pick a global IPv6 address at random, e.g. Google's Public DNS address.

ip r get to 2001:4860:4860::8888 | perl -ne '/src ([\w:]+)/ && print "$1\n"'
2001:db8:f387:c818:5:2:0:1000

This asks Linux for the route to that destination. Perl parses the result looking for src and then prints the next field.

By providing a different destination, you may receive a different source address:

ip r get to ::1 | perl -ne '/src ([\w:]+)/ && print "$1\n"'
::1
2

Use the following command to view your IP address on Linux :

ifconfig

Normally, Ipv6 address looks like 2001:5c0:9168::/48 . If you are facing any conflict in your IP, follow the below steps to set an IP address again:

  1. To assign IPv6 IPs, make sure you have the iproute2 tools installed.
  2. Using them, let's start to assign your IPs.
  3. Make sure that the ipv6 module installed or not.

Then, use the following command to add new ip:

ip -f inet6 addr add 2001:5c0:9168::2/64 dev eth0

Afterwards, add default ip via

ip -f inet6 ro add default via 2001:5c0:9168::1 dev eth0

After completing your installation, just reconfigure/restart your IPv6 enabled services, like Apache, SSH etc.

Malvineous
  • 2,798
1

Here a way with ip and awk:

IPv4

ip addr show dev eth0 | awk '{if ($1=="inet") {print $2}}'

IPv6

ip addr show dev eth0 | awk '{if ($1=="inet6") {print $2}}'
Althor49
  • 11
  • 1
1

This works on Debian / Raspbian (raspberry OS).

hostname -I | cut -d " " -f 2

hostname -I returns a line formatted: internal_ipv4 ipv6 the IPs attributed to the current used interface (eventually eth0 or wlan0, I think...). just like the following one, (note: fake numbers for demonstration purposes):

192.168.0.64 2001:8905:6322:8401:a63b:35c1:9d20:9a4a

Then just pick the second column using

cut -d " " -f 2

that is, cut using delimiter space and choose field 2.

Dave M
  • 13,250
Ramalho
  • 11
1

This returns the IPv6 of the very first used interface:

hostname -I | egrep -o '[0-9a-z:]+:[0-9a-z:]+' | head -n 1

Example:

hostname -I
192.168.178.9 172.19.0.1 2003:e0:a73b:f700:b63e:99f0:f5a8:c72d 2003:e0:a73b:f700:b63e:99f0:f5a8:c72e

Result:

hostname -I | egrep -o '[0-9a-z:]+:[0-9a-z:]+' | head -n 1
2003:e0:a73b:f700:b63e:99f0:f5a8:c72d

head -n 2 | tail -1 would return the second and head -n 3 | tail -1 the third result.

mgutt
  • 1,198
  • 2
  • 17
  • 35
1

If you want to find the public IPv6 address you can do this with the dig command and then piping this into the sed command to remove the closing quotes.

dig -6 TXT +short o-o.myaddr.l.google.com @ns1.google.com | sed 's|"||g'
0
ip addr show dev eth0 | sed -e's/^.*inet6 \(2001[^ ]*\)\/64 scope global dynamic.*$/\1/;t;d'