2

I need to send a simple request to one of my server on defined intervals, let's say one every 2 seconds, in order to tell my server my machine's IP address(since I've dynamic one). I'm currently doing it in a while loop with a delay for std::system call for curl command with --silent option and redirecting rest to /dev/null. Something like this -

curl -s 'http://example.com' > /dev/null

The server currently parses the request and finds out the required IP address from it. Is there any other way to do this?

hg_git
  • 2,884
  • 6
  • 24
  • 43
  • 1
    See here: http://stackoverflow.com/questions/2283494/get-ip-address-of-an-interface-on-linux for getting your own IP adress. Then you can open a socket to the server and send it there – Hayt Sep 01 '16 at 10:45
  • @Hayt the machine and server are on different networks. Machine has dynamic IP, server has a fixed one. Hence machine can hit server with request but not the other way round. – hg_git Sep 01 '16 at 10:47
  • 1
    What protocol do you use? – BiagioF Sep 01 '16 at 10:49
  • 1
    This code should be executed on your machine not the server. It then can get it's own IP address and send it to the server via whatever protocol you use. You could also use libcurl to write code which does your curl request instead of using system. – Hayt Sep 01 '16 at 10:51
  • @BiagioFesta I'm open to using any protocol. Currently I'm using simple HTTP GET requests. – hg_git Sep 01 '16 at 10:52
  • @Hayt sorry for misunderstanding, yes I've and am sending my own IP address to server. I'm asking for a better way since system call is essentially spinning up new processes for such a short task of sending ip address. – hg_git Sep 01 '16 at 10:55
  • 1
    The problem with the code @Hayt pointed to is that you have to know the interface name. The better approach is to use `getsockname` on a socket already connected to the server – Serge Sep 01 '16 at 10:55
  • 2
    there are several ways to do this. Native C would be to open a socket to the server (you also need a listening application running on the server) and then you can send dummy data and parse the IP header on the server to get the sender address. You can also send the IP adress itself as data so you don't need to parse headers. – Hayt Sep 01 '16 at 10:55
  • 1
    @hayt the address hardly would change while the host is up and connected to a segment, otherwise the host would shut down any existing tcp connections – Serge Sep 01 '16 at 10:59
  • 1
    You can simply use [libcurl](https://curl.haxx.se/libcurl/). Once every 2 seconds is a lot, why not only sent it if its changes? – Galik Sep 01 '16 at 11:03
  • @Galik you're right, I should and will monitor the change and then send it :) – hg_git Sep 01 '16 at 11:05

1 Answers1

4

Another alternative would be sending a simple UDP datagram packet. The server can obtain the sender's address, upon receipt, equally well.

That requires a little bit less overhead than establishing a TCP connection. Of course, UDP offers no guarantee of deliverability, and an occasional UDP datagram would be lost; but since you're pinging the server regularly that should be fine. More importantly, however, is that a UDP sender's IP address is trivially forged. Whether or not this is an issue for your application is something that only you can determine.

If you're going to stick with TCP, one thing you can do is to establish a socket connection yourself. Let's examine what executing system(), just for the purpose of having curl do a dummy connection, involves:

  1. forking a new child process.

  2. the child process executing /bin/bash, passing it the command to parse.

  3. Bash reading $HOME/.bashrc, and executing any commands in there. If your shell is something other than bash, the shell will have its own equivalent of a startup script to execute.

  4. The shell forking a new child process.

  5. The child process executing curl.

  6. The loader finding all of the libraries that curl requires, and opening them.

  7. curl now executes. Only then, after all this work, there will be code running to open a socket and attempt to connect to the remote host.

Steps 1 through 6 can be trivially skipped, simply by creating a socket, and connecting, yourself. It's not rocket science. socket(), connect(), close(), that's it. This task does not require HTTP. The server process only needs to socket(), bind(), listen(), and accept(), and then obtain the IP address from the connection. Done.

Sam Varshavchik
  • 114,536
  • 5
  • 94
  • 148
  • wait, is it possible to forge a udp packet's ip address field? I wasn't aware of this fact, how would that be possible given send() calls are handled by kernel only :/ – hg_git Sep 01 '16 at 11:07
  • @hg_git it is possible to spoof any data unless you are using end-to-end authentication of data sent by means of ssl, tls, ipsec, what ever else – Serge Sep 01 '16 at 11:09
  • Yes, it's trivial to forge the udp packet's sender. The kernel offers a raw socket interface, which you can use to spew out any packet you want. – Sam Varshavchik Sep 01 '16 at 11:09
  • You can store the IP in the payload and digitally sign it – rustyx Sep 01 '16 at 11:28
  • @RustyX could you provide any resources I could look into to understand how should i do the digital signing process :) – hg_git Sep 01 '16 at 15:23
  • Step 1 to understanding how to "do the digital signing" would be to spend a month, or two, learning the basic theories of public/private key cryptography. Much like most other advanced technical subjects, there is no single magic button you can push to give you instant gratification. Only after you understand the basic fundamentals, then you can begin the job of employing the cryptographic libraries of your operating system to implement digitally-signed messages between the client and the server. – Sam Varshavchik Sep 01 '16 at 15:54