62

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
2
  • write a shell script and put those commands in there: voila, you have now created a "single" command.
    – akira
    Aug 31, 2012 at 17:13
  • 4
    When dealing with IPv6 it is not really recommended to limit to a single addresses. There can be multiple global addresses, multiple link-local addresses, multiple site-local addresses... Aug 31, 2012 at 17:25

14 Answers 14

59
ip -6 addr

will show your IPv6 addresses.

2
  • 1
    % ip -6 addr 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 inet6 ::1/128 scope host valid_lft forever preferred_lft forever ... still greppable
    – akira
    Aug 31, 2012 at 17:13
  • 12
    This does not solve the stated question. OP wants a single command line to retrieve one IPv6 (which probably means the primary public one). So either ip -6 addr show dev eth0 | sed -n 's|^.*inet6 \([^ ]*/64\).*$|\1|p' or ip -6 addr show dev eth0 | awk '/inet6/{print $2}' could be used as a base and OP can extend/edit them for his specific use case.
    – rwenz3l
    Oct 30, 2018 at 21:04
12

/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.

2
  • 1
    there is way too much piping of grep into awk, this could be collaspe into a single awk ` awk -F '[ \t]+|/' '$3 == "::1" { next;} $3 ~ /^fe80::/ { next ; } /inet6/ {print $3} '`
    – Archemar
    Mar 26, 2016 at 9:02
  • That command outputs nothing on Ubuntu server 20.10
    – Link14
    Jan 29, 2022 at 18:09
11

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'
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
3

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.

1
  • 1
    ifconfig is obsolete on Linux and should no longer be used. Modern Linux distros don't even install it by default anymore (unless some ancient package requires it). Oct 30, 2018 at 22:47
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
0
2

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.

2
  • 1
    Good call regarding -json! Alternative to your version: ip -json -6 addr show enp0s25 scope global | jq -r '.[0].addr_info[0].local' Jul 8, 2023 at 15:28
  • @MatthiasBraun good call - I always forget you can limit scope on the ip commandline.
    – Tom
    Jul 12, 2023 at 8:42
1

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.

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}}'
0
ip addr show dev eth0 | sed -e's/^.*inet6 \(2001[^ ]*\)\/64 scope global dynamic.*$/\1/;t;d'
0

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.

0

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.

0

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]+'

0

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'

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .