Opened 20 months ago

Last modified 20 months ago

#2012 open defect

Router listens on public interface when local address is configured as 127.0.0.X instead of 127.0.0.1

Reported by: slumlord Owned by:
Priority: minor Milestone: undecided
Component: router/general Version: 0.9.30
Keywords: console, bind, localhost, public.ip Cc:
Parent Tickets:

Description (last modified by slumlord)

I set up an I2P router recently and found that it was listening for network traffic on a public interface when it would usually be listening on localhost or 127.0.0.1. The IP address configured on the system was 127.0.0.3/8 and /etc/hosts had been updated accordingly. I was able to fix most of these by using grep & changing all 127.0.0.1 entries to the correct IP in *.config. The I2P router's web server (for I2P default hidden webpage) was listening on port 7658 (on the external IP). This was fixed by changing a line in jetty.xml, if I recall correctly. I tried to configure the router to listen on ::3 as well but that does not seem to have worked at all.

I think there should be better auto-detection of local IP addresses when binding to them, especially if it has been defined in the /etc/hosts file. If there is an IP address on the 127.0.0.1/8 subnet then that should be used for any local listeners instead of trying to bind to a public IP. I don't know if it's a good idea to restrict all network binding (except for the external port) to addresses only in a private address range.

If the router does bind to a public IP address for any service that would normally be listening on localhost (perhaps the system is only configured with a public IP), there should be some kind of warning shown to the user as something like this could easily go unnoticed if not intentional.

Subtickets (add)

Change History (11)

comment:1 Changed 20 months ago by slumlord

I2P version: 0.9.30-0
Java version: Oracle Corporation 1.8.0_121 (OpenJDK Runtime Environment 1.8.0_121)
Wrapper version: 3.5.30
Server version: 9.2.21.v20170120
Servlet version: Jasper JSP 2.3 Engine
JSTL version: standard-taglib 1.2.0
Platform: FreeBSD amd64
Jcpuid version: 3
Processor:
Jbigi: Locally optimized library libjbigi-freebsd-coreihwl_64.so loaded from file
Jbigi version: 3
GMP version: 6.0.0

comment:2 Changed 20 months ago by zzz

  • Status changed from new to open

Huh? What port/service was listening to a public interface? The router itself, i.e. SSU and NTCP? Or what?

what's the issue?

1) Some port should be listening to 127.0.0.1 but is bound to a public interface

or

2) Some port should auto-discover 127.0.0.3 but is bound to 127.0.0.1?

or both?

Most things should bind to 127.0.0.1 and if that's not a valid address things will break.

comment:3 Changed 20 months ago by slumlord

Hi,

Sorry if the description was confusing, let me try and clarify.

Some ports should be listening on the local address configured for the system (in this case, a FreeBSD jail) but it somehow binds these to the public interface/IP instead. Since the 127.0.0.1 address is reserved for the host on this system, the jail is assigned 127.0.0.3/8 as loopback address - this address is configured on the loopback interface: lo0 and is also added to the /etc/hosts file (in place of 127.0.0.1).

An I2P router, when first started up, does not seem to recognize 127.0.0.3/8 as a valid loopback address and binds some ports to the public IP instead. This jail does not have the 127.0.0.1 address, only 127.0.0.3 & a public IP.

From RFC-5735:

   127.0.0.0/8 - This block is assigned for use as the Internet host
   loopback address.  A datagram sent by a higher-level protocol to an
   address anywhere within this block loops back inside the host.  This
   is ordinarily implemented using only 127.0.0.1/32 for loopback.  As
   described in [RFC1122], Section 3.2.1.3, addresses within the entire
   127.0.0.0/8 block do not legitimately appear on any network anywhere.

(clearnet link - https://tools.ietf.org/html/rfc5735)

I just checked and it seems to bind port 32000 to the public interface as well. This is fixed by adding wrapper.port.address=127.0.0.3 to wrapper.config

If I recall correctly, I found that anything that should be listening on a local interface would be listening on the public IP, so ports 4444, 7657, 7658, 6668 as well as 32000. I will try this again in a fresh jail to be sure.

---

In the initial post, I wrote about trying to use ::3 as an IPv6 loopback address. I was mistaken about this - IPv6 loopback is only ::1

Last edited 20 months ago by slumlord (previous) (diff)

comment:4 Changed 20 months ago by zzz

  • Status changed from open to infoneeded

Your description is still a little confusing. 127.0.0.3/8 is not an address... it's a block (and the same as 127.0.0.0/8). 127.0.0.3 is an address.

OP says "The IP address configured on the system was 127.0.0.3/8 and /etc/hosts had been updated accordingly." Presumably that means /etc/hosts has a line "127.0.0.3 localhost". If /etc/hosts contains "127.0.0.3/8 localhost" that would be very wrong.

You propose "better auto-detection of local IP addresses" which makes it sound complicated, but this autodetection would be simple... standard DNS lookup of "localhost".

We replaced all instances of "localhost" with "127.0.0.1" back in 0.7.2, early 2009, when we enabled IPv6 in the JVM. As I recall, we had some issues with systems that had localhost set to an IPv6 address. A possible fix would be to go back to "localhost" for everything, but I'm scared that the old issues would resurface.

I'm still confused about OP claim that "listening for network traffic on a public interface when it would usually be listening on localhost or 127.0.0.1". If so, that would be a serious security issue, but you offer no details or evidence or logs. You followed up only with "does not seem to recognize 127.0.0.3/8 as a valid loopback address and binds some ports to the public IP instead". What ports? We need logs and specific services affected.

comment:5 Changed 20 months ago by slumlord

When I set up jails on FreeBSD, I have to specify an address as well as a subnet - so lo0|127.0.0.3/8, for example. The jail is configured to use the 127.0.0.3 address in the 127.0.0.0/8 subnet on the lo0 interface.

/etc/hosts contains the address without the subnet mask.

Comment 3 specifies "what ports?": 4444, 7657, 7658, 6668 as well as 32000 - this is from memory, as mentioned in comment 3, I will be recreating this issue in a fresh jail so that I can provide you with logs etc. I had an urgent need for a functioning I2P router so I did not have much time to investigate but just enough to document what I saw.

---

post to be updated with further information

comment:6 Changed 20 months ago by slumlord

  • Status changed from infoneeded to open

New jail:

> ifconfig

igb0: ...
inet XXX.XXX.XXX.XX9 netmask 0xffffffff broadcast XXX.XXX.XXX.XX9 # public IPv4
inet6 XXXX:XXXX:XXX:XXXX::4 prefixlen 64 # public IPv6

lo0: ...
inet 127.0.0.11 netmask 0xff000000 # private IPv4
> cat /etc/hosts

127.0.0.11 localhost

Checking to see if localhost resolves to 127.0.0.11

> getent hosts localhost

127.0.0.11        localhost

I realized after running the previous command that my DNS server is sitting outside the jail, querying the DNS server for localhost returns 127.0.0.1 (e.g. with host localhost), however the /etc/hosts file inside the jail has the correct value, it can be queried with getent hosts localhost. The DNS server is external to the jail and so does not know about the jail's internal networking configuration. I don't know how Java handles this but there may be a way to ensure that any local configuration (e.g. /etc/hosts) is checked and used when available.

A subsequent sockstat shows:

% sockstat
USER     COMMAND    PID   FD PROTO  LOCAL ADDRESS         FOREIGN ADDRESS
i2puser  java       59506 4  tcp4   XXX.XXX.XXX.XX9:32000 *:*
i2puser  java       59506 44 stream (not connected)
i2puser  java       59506 45 tcp4   XXX.XXX.XXX.XX9:31000 XXX.XXX.XXX.XX9:32000
i2puser  java       59506 62 tcp46  *:10179               *:*
i2puser  java       59506 64 tcp4   XXX.XXX.XXX.XX9:10629 ...:8443
i2puser  java       59506 65 tcp4   XXX.XXX.XXX.XX9:7657  *:*
i2puser  java       59506 78 stream (not connected)
i2puser  java       59506 83 udp46  *:10179               *:*
i2puser  java       59506 87 stream (not connected)
i2puser  java       59506 91 tcp4   XXX.XXX.XXX.XX9:7654  *:*
i2puser  java       59506 95 tcp4   XXX.XXX.XXX.XX9:7658  *:*
i2puser  java       59506 109 tcp4  XXX.XXX.XXX.XX9:10739 ...:15155
i2puser  java       59506 110 tcp4  XXX.XXX.XXX.XX9:6668  *:*
i2puser  java       59506 111 tcp4  XXX.XXX.XXX.XX9:7659  *:*
i2puser  java       59506 112 tcp4  XXX.XXX.XXX.XX9:4444  *:*
i2puser  java       59506 113 tcp4  XXX.XXX.XXX.XX9:7660  *:*
i2puser  i2psvc     59505 6  tcp4   XXX.XXX.XXX.XX9:32000 XXX.XXX.XXX.XX9:31000
?        ?          ?     ?  tcp4   XXX.XXX.XXX.XX9:10630 XXX.XXX.XXX.XX9:7657

left 2 ip addresses in here, please remove from logs thanks

Last edited 20 months ago by slumlord (previous) (diff)

comment:7 Changed 20 months ago by slumlord

  • Description modified (diff)

comment:8 Changed 20 months ago by slumlord

  • Description modified (diff)

comment:9 Changed 20 months ago by zzz

afaik, there's no simple or portable way to configure or override how Java does lookups, it just uses glibc. Most of the services in comment 6 (444,6668,7659,7660) are set in i2ptunnel.config to 127.0.0.1, how those get magically bound to a public IP address instead (and without any error logs?) seems impossible, so perhaps it's an artifact of BSD jails, or sockstat output, or something. The other ports are the wrapper client/server, the console, and jetty.

As I said in comment 4, we don't use 'localhost' anymore as a default, anywhere, and it still isn't clear from your comment 6 what it would resolve to from java. So any issues in the OP are unlikely to be caused by DNS.

If, however, binding to 127.0.0.1 somehow escapes the jail and binds to a socket on the "parent" OS (whatever you call that) and then that gets reported as binding to the public IP, that's really odd, and I have no idea what to do about it.

comment:10 Changed 20 months ago by slumlord

It is binding all of these to the public IP that is configured exclusively for the jail's usage (it is not escaping the jail), instead of 127.0.0.11 --- 127.0.0.1 isn't available in the jail.

I2P is configured to use 127.0.0.1 by default, that isn't available (although 127.0.0.11 is, on the lo0 interface), I2P then binds to the IPv4 address on the public interface.

It is easy to change this on my system by editing a handful of config files (this is a headless system). It may be useful to echo the IP address configured for the auto-start services to the console? This way if i2p is listening on a public IP address, the user will see immediately.

comment:11 Changed 20 months ago by slumlord

Port 7654 was difficult to change, setting is on http://localhost:7657/configi2cp

i2puser  java       74196 4  tcp4   127.0.0.11:32000      *:*
i2puser  java       74196 59 tcp4   127.0.0.11:7657       *:*
i2puser  java       74196 96 tcp4   127.0.0.11:7658       *:*
i2puser  java       74196 110 tcp4  127.0.0.11:6668       *:*
i2puser  java       74196 111 tcp4  127.0.0.11:7660       *:*
i2puser  java       74196 112 tcp4  127.0.0.11:7659       *:*
i2puser  java       74196 113 tcp4  127.0.0.11:4444       *:*
i2puser  java       74196 116 tcp4  127.0.0.11:7662       *:*
i2puser  java       74196 131 tcp4  127.0.0.11:4445       *:*

---

reminder to never reveal your port number(s) publicly

Last edited 20 months ago by slumlord (previous) (diff)
Note: See TracTickets for help on using tickets.