Can't connect to 'localhost' in IO::Socket


W

Wolfram Humann

I'm using RPC::Lite to exchange data between two programs. I noticed
that when I run the client on the same machine as the server, I am
able to connect using the machine's name but not 'localhost'.
RPC::Lite uses IO::Socket and I found that I see the same problem with
the following command-line:

mymachine:/tmp> perl -MData::Dump=pp -MIO::Socket -E'$sock =
IO::Socket::INET->new( Proto => "tcp", PeerAddr => "mymachine",
PeerPort => 1700); pp $sock'
do {
require Symbol;
my $a = bless(Symbol::gensym(), "IO::Socket::INET");
*{$a} = {
io_socket_domain => 2,
io_socket_proto => 6,
io_socket_timeout => undef,
io_socket_type => 1,
};
$a;
}
mymachine:/tmp> perl -MData::Dump=pp -MIO::Socket -E'$sock =
IO::Socket::INET->new( Proto => "tcp", PeerAddr => "localhost",
PeerPort => 1700); pp $sock'
undef
mymachine:/tmp> perl -MData::Dump=pp -MIO::Socket -E'$sock =
IO::Socket::INET->new( Proto => "tcp", PeerAddr => "127.0.0.1",
PeerPort => 1700); pp $sock'
undef

Any idea why this is the case or how to further debug?
Thanks,
Wolfram
 
Ad

Advertisements

W

Wolfram Humann

You haven't shown us how the listening socket was created.

'localhost' (usually :) ) resolves to 127.0.0.1, whereas your machine
name will resolve to some other IP address(es) used by your machine. A
socket that's only listening on one of those addresses won't receive
connections addressed to the other(s).

Ah, good to know. I had a suspicion that this might be not so much a
perl issue but a problem of my shallow understanding of TCP.
If you don't supply a LocalAddr parameter, a listening IO::Socket::INET
will bind to 0.0.0.0 (sometimes called INADDR_ANY), which is a special
magic address meaning 'accept connections destined to this port on any
local address'. If you do supply LocalAddr, though, it will bind to the
address you supply, which means it won't accept connections to any other
address.

So I expanded my RPC::Lite::Server call to
RPC::Lite::Server->new({ Transports => ['TCP:port=1700,Host=' .
hostname(), 'TCP:port=1700,Host=localhost'] })
and voila, it works.
On most systems, you can use netstat(1) to see what addresses your
sockets are actually bound to. See your system documentation.
Maybe netstat is another thing I don't know well enough, but grep-ing
netstat's output for the port-number, I could only see it once the
connection was established but not while I only had the server waiting
for a client to connect.

Problem solved -- Thank you, Ben!
Wolfram
 
R

Rainer Weikusat

[...]
If you don't supply a LocalAddr parameter, a listening IO::Socket::INET
will bind to 0.0.0.0 (sometimes called INADDR_ANY), which is a special
magic address meaning 'accept connections destined to this port on any
local address'. If you do supply LocalAddr, though, it will bind to the
address you supply, which means it won't accept connections to any other
address.

So I expanded my RPC::Lite::Server call to
RPC::Lite::Server->new({ Transports => ['TCP:port=1700,Host=' .
hostname(), 'TCP:port=1700,Host=localhost'] })
and voila, it works.

It is usually more sensible to bind to the wildcard address,
especially considering that IP addresses are usually per-host and not
per-interface, meaning, by default, any address that's configured on
any public interface of some computer will reachable via all other
public interfaces (so-called 'weak end-system').
Maybe netstat is another thing I don't know well enough, but grep-ing
netstat's output for the port-number, I could only see it once the
connection was established but not while I only had the server waiting
for a client to connect.

By default, netstat doesn't display listening sockets. It can be
instructed to do wo with either the -l ('listening') or -a ('all')
flags.
 
W

Wolfram Humann

It is usually more sensible to bind to the wildcard address,
especially considering that IP addresses are usually per-host and not
per-interface, meaning, by default, any address that's configured on
any public interface of some computer will reachable via all other
public interfaces (so-called 'weak end-system').

So I would simply say Transports => ['TCP:port=1700,Host=']

with the corresponding netstat (thanks for the -l / -a tip!) reply:

tcp 0 0 *:1700
*:* LISTEN

Is that what you meant? Does this wildcard create any security issues
(exceeding those potentially present before by providing *any* TCP-
accessible service)?

Regards,
Wolfram
 
R

Rainer Weikusat

Wolfram Humann said:
It is usually more sensible to bind to the wildcard address,
especially considering that IP addresses are usually per-host and not
per-interface, meaning, by default, any address that's configured on
any public interface of some computer will reachable via all other
public interfaces (so-called 'weak end-system').

So I would simply say Transports => ['TCP:port=1700,Host=']

with the corresponding netstat (thanks for the -l / -a tip!) reply:

tcp 0 0 *:1700
*:* LISTEN

Is that what you meant? Does this wildcard create any security issues
(exceeding those potentially present before by providing *any* TCP-
accessible service)?

Usually no if the service is supposed to listening on a 'public'
address (here supposed to mean anything except 127.0.0.1) anyway, see my
remark about 'weak end-systems' above. Insofar desired, working
source-based access control can either be provided by the application
(by immediately closing connections from 'unwelcome' source addresses
after accepting them) or with the help of some kind of host- or
gateway-based packet filter.
 
W

Wolfram Humann

Usually no if the service is supposed to listening on a 'public'
address (here supposed to mean anything except 127.0.0.1) anyway, see my
remark about 'weak end-systems' above. Insofar desired, working
source-based access control can either be provided by the application
(by immediately closing connections from 'unwelcome' source addresses
after accepting them) or with the help of some kind of host- or
gateway-based packet filter.

Ok. Thanks again for your feedback,
Wolfram
 
Ad

Advertisements

M

Martijn Lievaart

Wolfram Humann said:
It is usually more sensible to bind to the wildcard address,
especially considering that IP addresses are usually per-host and not
per-interface, meaning, by default, any address that's configured on
any public interface of some computer will reachable via all other
public interfaces (so-called 'weak end-system').

So I would simply say Transports => ['TCP:port=1700,Host=']

with the corresponding netstat (thanks for the -l / -a tip!) reply:

tcp 0 0 *:1700
*:* LISTEN

Is that what you meant? Does this wildcard create any security issues
(exceeding those potentially present before by providing *any* TCP-
accessible service)?
Do note that Rainer is wrong there. IP addresses are bound to an
interface, always. DNS may not care about that and give you just an IP
address if you know the hostname, but if you're trying to connect,
especially on a LAN or on a local machine, it is *important* that you
known which interface is being listened on.

Sorry but Rainer is absolutely correct and you are absolutely wrong. It's
an important concept, so I suggest you Google it.

HTH,
M4
 
M

Martijn Lievaart

On Wed, 22 Feb 2012 12:16:34 +0000, Ben Morrow wrote:

I agree this has little to do with the OP's question, but the concepts
involved are important, and Wolfram was just plain wrong. It's a very
common misunderstanding and that is why I reacted.
Rainer was (implicitly) talking about using a specific socket binding as
a means of filtering connections by *source* address. He is quite
correct this isn't possible on a weak ES; it's also just as stupid and
dangerous as any other form of filtering by IP that isn't backed up by
some more secure form of authentication.

Actually he wasn't. What he was pointing out (which had nothing to do
with the OPs question, I agree) is that a WES accepts connection on any
address on any interface. Not just on the interface the address is
configured on.
The OP's problem was to do with a specific socket binding filtering
connections by *destination* address. This happens on all (not-
completely-broken) systems: even a vanilla unfirewalled Unix system
won't accept connections destined for one address on a socket bound to a
different address. It's often important to be careful about socket
Correct.

bindings for this reason: for instance, a server that uses SSL or
Kerberos that thought it was serving on address A will fail to
authenticate connections where the client was trying to connect to
address B.

I don't know about Kerberos, but this is not true for SSL.
In any case, Unix systems can generally be configured as strong ESs now,
at least as far as requirement (A) (rejecting packets coming in on the
wrong interface) goes. Most firewall packages have some sort of
'antispoof' mechanism that does this.

Ah, no. You are confusing anti-spoofing with strong end systems
requirements. One deals with source addresses, the other with destination
addresses. If you want strong end behavior, you have to put that into
firewall rules yourself.

M4
 
R

Rainer Weikusat

Ben Morrow said:
Quoth Martijn Lievaart said:
So I would simply say Transports => ['TCP:port=1700,Host=']

with the corresponding netstat (thanks for the -l / -a tip!) reply:

tcp 0 0 *:1700
*:* LISTEN

Is that what you meant? Does this wildcard create any security issues
(exceeding those potentially present before by providing *any* TCP-
accessible service)?

Do note that Rainer is wrong there. IP addresses are bound to an
interface, always. DNS may not care about that and give you just an IP
address if you know the hostname, but if you're trying to connect,
especially on a LAN or on a local machine, it is *important* that you
known which interface is being listened on.

Sorry but Rainer is absolutely correct and you are absolutely wrong. It's
an important concept, so I suggest you Google it.

You could at least give a reference: RFC 1122, section 3.3.4.2
'Multihoming Requirements'. It is an important concept, but it isn't in
any way related to the OP's question.

Rainer was (implicitly) talking about using a specific socket binding as
a means of filtering connections by *source* address. He is quite
correct this isn't possible on a weak ES; it's also just as stupid and
dangerous as any other form of filtering by IP that isn't backed up by
some more secure form of authentication.

The OP's problem was to do with a specific socket binding filtering
connections by *destination* address.

The OP's problem was that he bound a socket to an address configured
on the host and then tried to connect to the server using the loopback
address. This didn't work and the second solution was to create two
server sockets, one bound to the public address and the other bound to
the loopback address. At this point, I suggested to bind to the
wildcard address instead since this will enable connections using all
addresses configured on the host with a single socket. Further, I
pointed out that this has no 'security implementations' since binding
to a destination address restricts the destination addresses a client
can use (should I really have repeated this explicitly since it was
demonstrated two postings ago?) BUT NOT the host interfaces which can
be used to reach this destination address, except if some system is
specifically configured to do so and systems usually aren't.

Please note that this has no relation to 'antispoofing': This refers
to doing some kind of plausibility check of a source address based on
the interface it arrived on, eg, drop the datagram if it was received
on an interface but the host wouldn't route datagrams destined at the
source address out of this interface (so-called 'reverse path' check).

Provided I have a computer in a LAN segment where a host which also
has an interface on another LAN segment has an interface, I can
configure a suitable 'host route' for the protocol address of the
other interface and reach that without going through an intermediate
gateway.
 
R

Rainer Weikusat

Ben Morrow said:
Quoth Martijn Lievaart <[email protected]>:
[...]
I don't know about Kerberos, but this is not true for SSL.

Suppose I have a machine with two names and two addresses, 'foo' =>
10.0.0.1 and 'bar' => 10.0.0.2, and an SSL webserver listening on the
wildcard address with a certificate for 'foo'.

Suppose I've intentionally configured a DNS server and a web server
such that the DNS information is inconsistent with the web server
configuration ...
If a client connects to https://bar/, it will see an invalid certificate.

.... it is then conceivable that this inconsistent configuration breaks
transparent HTTPS access to this server! How this relates to the
original problem seems somewhat unclear to me. The solution to this
contrived problem is to fix the DNS configuration: Provided that
clients can legitmately access the same HTTPS server using either
address, the A records for both need to associate the same name to
each address.

BTW, at least for Apache, your example doesn't exactly make sense
because the HTTP server usually listens on the wildcard address and
matches incoming requests to virtual SSL servers by looking for a
virtual server configuration matching the destination address of the
request and using the certificate etc configured for this virtual
server.
 
M

Mart van de Wege

Martijn Lievaart said:
Wolfram Humann said:
It is usually more sensible to bind to the wildcard address,
especially considering that IP addresses are usually per-host and not
per-interface, meaning, by default, any address that's configured on
any public interface of some computer will reachable via all other
public interfaces (so-called 'weak end-system').

So I would simply say Transports => ['TCP:port=1700,Host=']

with the corresponding netstat (thanks for the -l / -a tip!) reply:

tcp 0 0 *:1700
*:* LISTEN

Is that what you meant? Does this wildcard create any security issues
(exceeding those potentially present before by providing *any* TCP-
accessible service)?
Do note that Rainer is wrong there. IP addresses are bound to an
interface, always. DNS may not care about that and give you just an IP
address if you know the hostname, but if you're trying to connect,
especially on a LAN or on a local machine, it is *important* that you
known which interface is being listened on.

Sorry but Rainer is absolutely correct and you are absolutely wrong. It's
an important concept, so I suggest you Google it.
Martijn,

On what interface will a host answer ARP queries?

That's the interface the IP is bound to. In general deployments, more is
not needed, if that means the host answers on *all* interfaces.

Yes, I know there are specialist tricks that work around this. For
ordinary server programming bringing that up is needless pedantry.

Mart
 
Ad

Advertisements

R

Rainer Weikusat

[...]
There are various ways around this, the most obvious being to serve a
different certificate based on the incoming destination address
(assuming you have one), but they all require being aware of the fact
you are listening on multiple addresses. It's often easier to manage
this if you have separate sockets listening on the individual addresses
than with a wildcard.

There's no need to 'manage this' by writing (or downloading :->)
application code which maintains a userspace database of socket <->
address bound to this socket mappings, the kernel already does that.

[[email protected]]~ $perldoc -f getsockname
getsockname SOCKET
Returns the packed sockaddr address of this end of the
SOCKET connection, in case you don't know the address because
you have several different IPs that the connection might have
come in on.


use Socket;
$mysockaddr = getsockname(SOCK);
($port, $myaddr) = sockaddr_in($mysockaddr);
printf "Connect to %s [%s]\n",
scalar gethostbyaddr($myaddr, AF_INET),
inet_ntoa($myaddr);


[formatting changed]
 
R

Rainer Weikusat

Mart van de Wege said:
Martijn Lievaart said:
It is usually more sensible to bind to the wildcard address,
especially considering that IP addresses are usually per-host and not
per-interface, meaning, by default, any address that's configured on
any public interface of some computer will reachable via all other
public interfaces (so-called 'weak end-system').

So I would simply say Transports => ['TCP:port=1700,Host=']

with the corresponding netstat (thanks for the -l / -a tip!) reply:

tcp 0 0 *:1700
*:* LISTEN

Is that what you meant? Does this wildcard create any security issues
(exceeding those potentially present before by providing *any* TCP-
accessible service)?

Do note that Rainer is wrong there. IP addresses are bound to an
interface, always. DNS may not care about that and give you just an IP
address if you know the hostname, but if you're trying to connect,
especially on a LAN or on a local machine, it is *important* that you
known which interface is being listened on.

Sorry but Rainer is absolutely correct and you are absolutely wrong. It's
an important concept, so I suggest you Google it.
Martijn,

On what interface will a host answer ARP queries?

That's the interface the IP is bound to.

arp_filter - BOOLEAN

[...]
0 - (default) The kernel can respond to arp requests with addresses
from other interfaces. This may seem wrong but it usually makes
sense, because it increases the chance of successful communication.
IP addresses are owned by the complete host on Linux, not by
particular interfaces.

http://www.linuxfoundation.org/collaborate/workgroups/networking/ip-sysctl

-----------------

Description

Determine whether a packet arriving on a non-forwarding interface
can be accepted for an IP address that is not explicitly
configured on that interface. If ip_forwarding is enabled, or
xxx:ip_forwarding for the appropriate interfaces is enabled, then
this parameter is ignored, because the packet is actually
forwarded.

Refer to RFC 1122 3.3.2.4.

Default

0 (loose multihoming)
-------------------

http://docs.oracle.com/cd/E19683-01/806-7009/chapter4-29/index.html

I'm presently not in the mood to hunt down information about the
default configuration of more operating systems.

[...]
For ordinary server programming bringing that up is needless pedantry.

There was a question regarding 'security implications' of binding a
TCP socket to the wildcard address and this was part of the answer.
 
M

Martijn Lievaart

On what interface will a host answer ARP queries?

Most OSses, all interfaces, for all IP addresses.
That's the interface the IP is bound to. In general deployments, more is

No, it's not.
not needed, if that means the host answers on *all* interfaces.

This doesn't make sense to me. Are you saying all IP addresses are bound
to all interfaces?
Yes, I know there are specialist tricks that work around this. For
ordinary server programming bringing that up is needless pedantry.

No specialist tricks, just how common OSses work out of the box.

Martijn
 
Ad

Advertisements

M

Mart van de Wege

Martijn Lievaart said:
Most OSses, all interfaces, for all IP addresses.
So, for the *outside* world, it can be assumed to be on all interfaces.

For the server administrator and a programmer, it requires an interface,
even a virtual one, to even set up an IP address.
No, it's not.


This doesn't make sense to me. Are you saying all IP addresses are bound
to all interfaces?
Yes, I dropped an 'even' there. Should be 'even if...'.

I maintain that the low-level details are needless pedantry in the
context of OP's question. It's like saying the world's militaries are
wrong to use Newtonian mechanics to plot artillery fire.

That may be technically wrong, but bringing up relativity does not help
to understand ballistic trajectories better, it only over-complicates
matters; thus it is wrong.

I accept that on the strict definition of the terms you and Rainer
consider me wrong. Technically you're right; I maintain an advanced
routing setup in our three datacenters, so I know and use all the
techniques you talk about. But context is everything, and I judged
Rainer's remarks far enough out of context to consider *him* wrong.

Mart
 
Ad

Advertisements


Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Top