8

I would like Apache to listen on the link-local ipv6 address on a particular interface. I have the following line in my httpd.conf:

Listen [fe80::a00:16ff:fe89:420f]:80

Which is based on the Apache documentation here: https://httpd.apache.org/docs/2.4/bind.html "IPv6 addresses must be enclosed in square brackets"

My operating system/Apache version details are as follows:

$ httpd -v
Server version: Apache/2.4.18 (Unix)
Server built:   Dec 14 2015 08:05:54
$ uname -rv
4.3.3-3-ARCH #1 SMP PREEMPT Wed Jan 20 08:12:23 CET 2016

The result shown using journalctl -e is:

(22)Invalid argument: AH00072: make_sock: could not bind to address [fe80.....

IPv6 is working because I have sshd and dnsmasq listening. I have tried appending two different scope ID suffixes to the address. You can use either the interface id 3 or name net1 as a scopeid in both ping6 and sshd.

$ ip addr | grep -Po "^\d: \S+"
1: lo:
2: net0:
3: net1:

$ for scopeid in 3 net1; do ping6 -c 1 fe80::a00:16ff:fe89:420f%$scopeid; done | grep loss
1 packets transmitted, 1 received, 0% packet loss, time 0ms
1 packets transmitted, 1 received, 0% packet loss, time 0ms

sshd_config works with either: ListenAddress fe80::a00:16ff:fe89:420f%3

or: ListenAddress fe80::a00:16ff:fe89:420f%net1

So with all this in mind I tried the following in httpd.conf

Listen [fe80::a00:16ff:fe89:420f%3]:80

and Listen [fe80::a00:16ff:fe89:420f%net1]:80

Adding either scopeid made Apache fail earlier in its start up process. journalctl -e shows a syntax error when parsing httpd.conf as follows:

AH00526: Syntax error on line 52 of /etc/httpd/conf/httpd.conf:
Scope id is not supported

Apache listens on the localhost ipv6 if I do Listen [::1]:80

I would expect Listen 80 to get Apache to bind to both ipv4 and ipv6, but it doesn't. It only binds to ipv6 addresses - netstat shows:

tcp6  0  0    :::80    :::*     LISTEN

In this case, Apache does accept requests on the link-local address on net1. I have to specify 0.0.0.0:80 or a specific ipv4 address for it to listen on ipv4.

So, how do I make Apache bind to one specific link-local address (not all of them - I want to avoid listening on other interfaces), or is it just not possible for Apache to listen on a link-local ipv6 address?

bao7uo
  • 1,664
  • 11
  • 24
  • Is your interface named `1` or `net1`? Either seems unlikely, so it's unclear why you attempted to use these. – Michael Hampton Jan 22 '16 at 23:17
  • 1
    You didn't include the scope in the link-local address. You need to do that sine the same link-local subnet is on all interfaces, and the scope determines which interface to use. Unfortunately, not all applications can use an address with the scope attached, and those applications basically cannot use specific link-local addresses. – Ron Maupin Jan 23 '16 at 01:33
  • The error message `Scope id is not supported` certainly suggests that it isn't supported - at least not with the version of Apache that you are using. I couldn't get Apace to do it either. Listening on `::` will accept connections over link-local addresses, that's about as close to an answer as I can get. Any more definitive answer than that would have to be based on a reading of the actual source code. – kasperd Jan 23 '16 at 15:24
  • 1
    Thanks kasperd, I tried one last thing before resorting to the source code and it worked, so I've added an answer below. – bao7uo Jan 23 '16 at 18:15

1 Answers1

6

Having spent some time on this it seems that the Apache documentation could be misleading, although I may have missed something. It says IPv6 addresses must be enclosed in square brackets. This is true for non link-local addresses. But I have now discovered that link-local addresses can be used, and must include a scope id, but without the square brackets. See below:

Apache documentation:

$ wget -q -O- https://httpd.apache.org/docs/2.4/bind.html | grep -Pao "(?<=p.)IPv6[ a-z]+"
IPv6 addresses must be enclosed in square brackets

My configuration:

$ grep -R ^Listen /etc/httpd/conf/
/etc/httpd/conf/httpd.conf:Listen fe80::a00:16ff:fe89:420f%3:80
/etc/httpd/conf/extra/httpd-ssl.conf:Listen fe80::a00:16ff:fe89:420f%net1:443

As you can see, I've used the interface id for the scope id with port 80, and the interface name for the scope id with port 443. This is just to show that either the interface id or name can successfully be used as the scope id.

Results:

$ sudo netstat -pant | grep -i httpd
tcp6   0    0 fe80::a00:16ff:fe89::80 :::*  LISTEN   709/httpd
tcp6   0    0 fe80::a00:16ff:fe89:443 :::*  LISTEN   709/httpd
bao7uo
  • 1,664
  • 11
  • 24
  • 1
    +1 Good find. Although I would consider this more of a bug than a feature. – Dubu Jan 24 '16 at 22:51
  • It doesn't seem to be a bug - curl and apache and presumably more all seem to use the same syntax. If link local, you drop the [] and add %eth0 for example. Great find though, this was a life saver. – Goblinhack Apr 13 '16 at 15:25
  • Can confirm that the no-brackets, explicit-interface syntax works. On my instance, I have `Listen fe80::20c:29ff:fe53:2218%eth0:443` and it works perfectly. – JamesTheAwesomeDude Jul 28 '17 at 18:03
  • This works for ListenAddress in sshd_config! ... This feels wrong, like am I able to specify interface or not...oh well – Ray Foss Jan 29 '20 at 19:58