FAQ
Hi,


I have a Python application that communicates with a server via telnet.
Host and port of the server are supplied by the user when the
application is started.


How can I determine from within the application whether the server's
host actually is the local host? (In that case I could implement an
operation not available in the telnet-based protocol by directly
accessing the local filesystem.)


Sounds like there should be an obvious solution. Unfortunately, I
haven't found it yet :-)


Malte

Search Discussions

  • Chris Angelico at Nov 25, 2013 at 11:07 pm

    On Tue, Nov 26, 2013 at 6:35 AM, Malte Forkel wrote:
    I have a Python application that communicates with a server via telnet.
    Host and port of the server are supplied by the user when the
    application is started.

    How can I determine from within the application whether the server's
    host actually is the local host? (In that case I could implement an
    operation not available in the telnet-based protocol by directly
    accessing the local filesystem.)

    Two easy ways you could do this. I would be inclined to do what
    PostgreSQL and others do, and have an explicit indication that you
    want to use a local method: for instance, the name "localhost". Use of
    anything else (including "127.0.0.1") means you use TCP/IP as normal,
    but the strict word "localhost", which is normally equivalent to the
    address 127.0.0.1, would signal your app to use the direct method (for
    PostgreSQL, that's a Unix socket rather than a TCP one). This means
    you can still force telnet to be used even if you're working locally -
    good for debugging.


    Alternatively, you can simply query the current network interfaces for
    their IPs, and see if the IP you were given is in that list. I don't
    know of a way to do that in core Python, but the C function you need
    is getifaddrs(), and this claims to wrap all that up nicely:


    https://pypi.python.org/pypi/netifaces


    This method would detect, for instance, that calling up 192.168.0.19
    port 12345 is a local lookup, because eth0 has address 192.168.0.19,
    and that 192.168.2.2 port 54321 is local too, because wlan0 has
    address 192.168.2.2.


    If you aren't too concerned with running this on multiple platforms
    (which seems likely - working with the local filesystem implies you
    know a lot about what the server and client are doing), you could
    simply parse the output of 'ip addr', 'ipconfig', 'ifconfig', or some
    equivalent network utility for your platform. That might be easier
    than playing with the package, depending on environment. But it'd be
    even simpler - and in some ways better - to be explicit about "use a
    direct connection rather than TCP".


    ChrisA
  • Malte Forkel at Nov 26, 2013 at 11:23 am

    Am 26.11.2013 00:07, schrieb Chris Angelico:
    Two easy ways you could do this. I would be inclined to do what
    PostgreSQL and others do, and have an explicit indication that you
    want to use a local method: for instance, the name "localhost". Use of
    anything else (including "127.0.0.1") means you use TCP/IP as normal,
    but the strict word "localhost", which is normally equivalent to the
    address 127.0.0.1, would signal your app to use the direct method (for
    PostgreSQL, that's a Unix socket rather than a TCP one). This means
    you can still force telnet to be used even if you're working locally -
    good for debugging.
    Unfortunately, I can't rely on the user to use a specific way to specify
    the (local) host.

    Alternatively, you can simply query the current network interfaces for
    their IPs, and see if the IP you were given is in that list. I don't
    know of a way to do that in core Python, but the C function you need
    is getifaddrs(), and this claims to wrap all that up nicely:

    https://pypi.python.org/pypi/netifaces

    This method would detect, for instance, that calling up 192.168.0.19
    port 12345 is a local lookup, because eth0 has address 192.168.0.19,
    and that 192.168.2.2 port 54321 is local too, because wlan0 has
    address 192.168.2.2.
    That's a very nice module which I wasn't aware of. But if possible I
    wouldn't want to force the user to install a (binary) extension module.
    Finding the right module for his platform and version of Python might be
    too difficult.

    If you aren't too concerned with running this on multiple platforms
    (which seems likely - working with the local filesystem implies you
    know a lot about what the server and client are doing), you could
    simply parse the output of 'ip addr', 'ipconfig', 'ifconfig', or some
    equivalent network utility for your platform. That might be easier
    than playing with the package, depending on environment.
    The application is run under Windows as well. So I'd have to parse the
    output of other network utilities as well, possibly in a variety of
    languages.


    Thanks for your suggestions! I'm sorry I'm so picky. May be there just
    is no easy solution.


    Malte
  • Ben Finney at Nov 25, 2013 at 11:41 pm

    Malte Forkel <malte.forkel@berlin.de> writes:


    I have a Python application that communicates with a server via
    telnet. Host and port of the server are supplied by the user when the
    application is started.

    How can I determine from within the application whether the server's
    host actually is the local host? (In that case I could implement an
    operation not available in the telnet-based protocol by directly
    accessing the local filesystem.)

    On Unix, this is up to the person invoking the program: the ?sockets?
    facility allows for a host-local connection to appear as though it's
    going over a network.


         <URL:https://en.wikipedia.org/wiki/Localhost>
         <URL:https://en.wikipedia.org/wiki/Unix_domain_socket>


    In other words: Your program shouldn't go snooping around to
    second-guess the connection type; if the user asked for a TCP/IP
    connection, that's what they should get. If they want to take advantage
    of a local connection, they can use a Unix domain socket.


    --
      \ ?I wrote a song, but I can't read music so I don't know what it |
       `\ is. Every once in a while I'll be listening to the radio and I |
    _o__) say, ?I think I might have written that.?? ?Steven Wright |
    Ben Finney
  • Malte Forkel at Nov 26, 2013 at 11:26 am

    Am 26.11.2013 00:41, schrieb Ben Finney:
    On Unix, this is up to the person invoking the program: the ?sockets?
    facility allows for a host-local connection to appear as though it's
    going over a network.

    <URL:https://en.wikipedia.org/wiki/Localhost>
    <URL:https://en.wikipedia.org/wiki/Unix_domain_socket>

    In other words: Your program shouldn't go snooping around to
    second-guess the connection type; if the user asked for a TCP/IP
    connection, that's what they should get. If they want to take advantage
    of a local connection, they can use a Unix domain socket.

    Unfortunately, I can't rely on the user to use a specific way to specify
    the (local) host. Therefor, the application has to detect if it is run
    on the same host as the server.


    May be my description was incomplete and somewhat misleading. Let me try
    to provide more information.


    The server is running on a Linux host. The application might be run on
    any Windows or Linux host in the (local) network. When starting the
    application, the user can specify the server by host and and a port. If
    no host is specified, it defaults to localhost. If no port is specified,
    a couple of well known ports are tried. The application establishes the
    connection to the server using telnetlib.


    Most of the application's functionality uses the telnet connection to
    communicate with the server. One special operation is not available in
    the protocol, but can be implemented by a direct file-based operation if
    the application is run on the server itself. I would like to use that
    option if technically feasible.


    Malte
  • Chris Angelico at Nov 26, 2013 at 11:38 am

    On Tue, Nov 26, 2013 at 10:26 PM, Malte Forkel wrote:
    Most of the application's functionality uses the telnet connection to
    communicate with the server. One special operation is not available in
    the protocol, but can be implemented by a direct file-based operation if
    the application is run on the server itself. I would like to use that
    option if technically feasible.

    There is another way you might be able to do this. The server could
    simply create a cookie in the file system - say, a file in /tmp with a
    randomly-generated name - and it can announce that to the client. If
    the client sees the same file in what it sees as /tmp, then it can
    assume that it's running on the server. Obviously there's a miniscule
    probability of an accidental collision, and someone could deliberately
    fool it, but for a simple check, that might work.


    ChrisA
  • Malte Forkel at Nov 26, 2013 at 12:13 pm

    Am 26.11.2013 12:38, schrieb Chris Angelico:
    There is another way you might be able to do this. The server could
    simply create a cookie in the file system - say, a file in /tmp with a
    randomly-generated name - and it can announce that to the client. If
    the client sees the same file in what it sees as /tmp, then it can
    assume that it's running on the server. Obviously there's a miniscule
    probability of an accidental collision, and someone could deliberately
    fool it, but for a simple check, that might work.
    That is a clever idea. While I can't modify the server, I could look at
    the files on the host running the application and try to determine if
    they fit to information from the server about its files. If both match,
    I could then conclude that application host and server host probably are
    the same. But, I still couldn't be sure.


    Isn't there anything in telnetlib that can differentiate between a local
    connection and a remote connection? Or may be some unique property of
    each host that I could use?


    Malte
  • Chris Angelico at Nov 26, 2013 at 12:26 pm

    On Tue, Nov 26, 2013 at 11:13 PM, Malte Forkel wrote:
    That is a clever idea. While I can't modify the server, I could look at
    the files on the host running the application and try to determine if
    they fit to information from the server about its files. If both match,
    I could then conclude that application host and server host probably are
    the same. But, I still couldn't be sure.

    If you deliberately create a file with a random name, the chances of
    one existing with the same name on the client are infinitesimal unless
    someone's deliberately trying to confuse things... in which case I
    wouldn't worry about it.

    Isn't there anything in telnetlib that can differentiate between a local
    connection and a remote connection?

    No, because there's no such thing as a "local connection". For
    instance, I have two internet connections at my house, and I can
    telnet out on one of them and back in on the other - but both
    connections are NATted, so the machine itself doesn't have an IP that
    matches what I'm talking about here. I could have a socket connection
    from w.x.y.z port 12345 to a.b.c.d port 80, and there's no way
    telnetlib would recognize that as coming back to the same computer,
    because this computer's IP addresses are all RFC 1918 ones (127.0.0.1,
    192.168.0.19, 192.168.2.2).

    Or may be some unique property of
    each host that I could use?

    That's what I was intending the file to be. You could also look for
    some kind of signature, like the MAC address of the first network
    interface, but that's going to be no more reliable and potentially a
    lot harder to recognize.


    ChrisA
  • Malte Forkel at Nov 26, 2013 at 5:26 pm

    Am 26.11.2013 13:26, schrieb Chris Angelico:
    If you deliberately create a file with a random name, the chances of
    one existing with the same name on the client are infinitesimal unless
    someone's deliberately trying to confuse things... in which case I
    wouldn't worry about it.
    I wouldn't, either. But the server is an existing application that I
    can't extend. It does not support creating a file with a random name.

    No, because there's no such thing as a "local connection". For
    instance, I have two internet connections at my house, and I can
    telnet out on one of them and back in on the other - but both
    connections are NATted, so the machine itself doesn't have an IP that
    matches what I'm talking about here. I could have a socket connection
    from w.x.y.z port 12345 to a.b.c.d port 80, and there's no way
    telnetlib would recognize that as coming back to the same computer,
    because this computer's IP addresses are all RFC 1918 ones (127.0.0.1,
    192.168.0.19, 192.168.2.2).
    Thanks for the explanation. I guess I was hoping that I could use some
    property of a connection created with telnetlib or its socket to find
    out whether it was actually a host-local connection (i.e. a connection
    to 'localhost', '127.xx.xx.xx' or '<local_host_name>').


    So its either your initial suggestion of taking a hint from the user or
    comparing files on the server and the client.
  • Chris Angelico at Nov 26, 2013 at 10:56 pm

    On Wed, Nov 27, 2013 at 4:26 AM, Malte Forkel wrote:
    Thanks for the explanation. I guess I was hoping that I could use some
    property of a connection created with telnetlib or its socket to find
    out whether it was actually a host-local connection (i.e. a connection
    to 'localhost', '127.xx.xx.xx' or '<local_host_name>').

    So its either your initial suggestion of taking a hint from the user or
    comparing files on the server and the client.

    You can still have a unique file, then; all you sacrifice is the
    random name generation. And you can of course recognize 127.x.y.z as
    local - it's just not the _only_ way to detect a local connection.


    Since this is, presumably, an optimization, you could possibly just
    tell people that it'll run faster if they tell it 127.0.0.1 than if
    they tell it {whatever other IPs the server has}. That may end up
    sufficient. Otherwise, yeah, detect by filesystem with a
    manually-created file.


    ChrisA
  • Walter Hurry at Nov 26, 2013 at 11:08 pm

    On Wed, 27 Nov 2013 09:56:13 +1100, Chris Angelico wrote:

    On Wed, Nov 27, 2013 at 4:26 AM, Malte Forkel wrote:
    Thanks for the explanation. I guess I was hoping that I could use some
    property of a connection created with telnetlib or its socket to find
    out whether it was actually a host-local connection (i.e. a connection
    to 'localhost', '127.xx.xx.xx' or '<local_host_name>').

    So its either your initial suggestion of taking a hint from the user or
    comparing files on the server and the client.
    You can still have a unique file, then; all you sacrifice is the random
    name generation. And you can of course recognize 127.x.y.z as local -
    it's just not the _only_ way to detect a local connection.

    Since this is, presumably, an optimization, you could possibly just tell
    people that it'll run faster if they tell it 127.0.0.1 than if they tell
    it {whatever other IPs the server has}. That may end up sufficient.
    Otherwise, yeah, detect by filesystem with a manually-created file.

    How about checking the MAC address of the local network card on the
    client, and then comparing that against a file on the server?


    Easy enough with ifconfig and grep. I presume that there is also a way on
    Windows, but others will have to contribute that.
  • Chris Angelico at Nov 26, 2013 at 11:15 pm

    On Wed, Nov 27, 2013 at 10:08 AM, Walter Hurry wrote:
    Easy enough with ifconfig and grep. I presume that there is also a way on
    Windows, but others will have to contribute that.

    Since the server runs Linux, inability to run /sbin/ifconfig could
    safely be interpreted as "we're not running on the server". But I
    think this actually gains little over "is there a file called
    /tmp/_this_is_malte_forkel_on_his_server_9515343_", which would be
    fairly safe.


    ChrisA
  • Malte Forkel at Nov 27, 2013 at 10:32 pm

    Am 27.11.2013 00:15, schrieb Chris Angelico:
    Since the server runs Linux, inability to run /sbin/ifconfig could
    safely be interpreted as "we're not running on the server". But I
    think this actually gains little over "is there a file called
    /tmp/_this_is_malte_forkel_on_his_server_9515343_", which would be
    fairly safe.
    The server runs Linux, the client might be used under Windows as well.


    I can't modify the server. So there is no way to create a file
    /tmp/_this_is_malte_forkel_on_his_server_9515343 or to check whether it
    exists on the server side.
  • Gregory Ewing at Nov 26, 2013 at 11:37 pm

    Malte Forkel wrote:
    One special operation is not available in
    the protocol, but can be implemented by a direct file-based operation if
    the application is run on the server itself.

    What would happen if you tried the file-based method when
    it wasn't a local connection? Is there a danger of it
    "succeeding" on the wrong machine and damaging something?


    --
    Greg
  • Malte Forkel at Nov 27, 2013 at 10:30 pm

    Am 27.11.2013 00:37, schrieb Gregory Ewing:
    What would happen if you tried the file-based method when
    it wasn't a local connection? Is there a danger of it
    "succeeding" on the wrong machine and damaging something?
    I have been thinking about that.


    There is a slight risk that the client might be talking to a server on a
    remote host while there is a similar server running on the local
    machine. That (local) server then might use a file by the same name as
    the file on the remote server the client wants to operate on. In that
    (unlikely) case I would mix up things big time...
  • Michael Torrie at Nov 27, 2013 at 12:14 am

    On 11/25/2013 12:35 PM, Malte Forkel wrote:
    I have a Python application that communicates with a server via telnet.
    Host and port of the server are supplied by the user when the
    application is started.

    How can I determine from within the application whether the server's
    host actually is the local host? (In that case I could implement an
    operation not available in the telnet-based protocol by directly
    accessing the local filesystem.)

    Sounds like there should be an obvious solution. Unfortunately, I
    haven't found it yet :-)

    I believe socket.getsockname() can return the IP address of the
    connecting client if you're using standard tcp/ip sockets.
  • Malte Forkel at Nov 27, 2013 at 10:31 pm

    Am 27.11.2013 01:14, schrieb Michael Torrie:
    I believe socket.getsockname() can return the IP address of the
    connecting client if you're using standard tcp/ip sockets.
    The way you describe it, it sounds like it would require a change to the
    server. I can only modify the client. I'll try to find out how I could
    use that on the client.

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
grouppython-list @
categoriespython
postedNov 25, '13 at 7:35p
activeNov 27, '13 at 10:32p
posts17
users6
websitepython.org

People

Translate

site design / logo © 2022 Grokbase