2

I need to embed a simple script written in Python into my C application. The script simply downloads some content from the Internet, parses it and prints result into stdout. I need to bind outgoing IP address of every connection made by script, to make use of many IP addresses provided with a server. I can use either Python/C API or C system()/execve() functions. I prefer to do not modify a script itself since it uses liburl2 which doesn't support binding local IP directly.

I would be grateful for every hint.

Regards, Michal Pietras.

  • no idea what " I need to bind outgoing IP address of every connection made by script, to make use of many IP addresses provided with a server" should mean –  May 21 '11 at 12:09
  • Do you mean 'to make use of *one of* many IP addresses...'? – johnsyweb May 21 '11 at 12:13
  • @sentinel @Johnsywe My server has a few IPs on a single interface. I need to be able to establish outgoing connections from these addresses because there is a limit of connections from single IP address at server asked by a script. – Michal Pietras May 21 '11 at 12:21
  • possible duplicate of [Source interface with Python and urllib2](http://stackoverflow.com/questions/1150332/source-interface-with-python-and-urllib2) –  May 21 '11 at 12:27
  • @Sentinel I have read it but I would like to make it on interpreter level to avoid editing source code. Is there any way to bind local IP for all connection made by interpreter? – Michal Pietras May 21 '11 at 12:32
  • @Michal Pietras: it is sufficient to execute [the code from the answer](http://stackoverflow.com/questions/1150332/source-interface-with-python-and-urllib2/1150423#1150423) in the same interpreter before executing your script (`urllib2` code from your script will use the patched version of `socket.socket`). – jfs May 21 '11 at 17:20
  • @J.F. Sebastian: So I don't need even to edit the script? Can I just run the patching code and binded socket will be retained when I run the script? This is a great news to me. Thanks a lot, it seems to be an answer to my question. – Michal Pietras May 21 '11 at 22:53
  • @Michal Pietras: You don't need to edit the script, you just need to execute that code first. This is known as [monkey-patching](http://en.wikipedia.org/wiki/Monkey_patching). – johnsyweb May 22 '11 at 02:46

2 Answers2

1

You question is answered here: Source interface with Python and urllib2

Community
  • 1
  • 1
Jerome
  • 2,350
  • 14
  • 25
  • I have read it but I would like to make it on interpreter level to avoid editing source code. Is there any way to bind local IP for all connection made by interpreter? – Michal Pietras May 21 '11 at 12:28
  • To do this from outside of python, you would need to intercept calls to bind(): write a C wrapper which implements bind() and is installed as LD_PRELOAD, changes the parameters of bind system call, and forward the request to the real bind function. It seems it requires way more work than the work around urllib2 limitation given in the referenced answer. – Jerome May 21 '11 at 12:58
  • Thanks a lot. I hopped that I can accomplish it more easily. The script I use is a little bit complex and I am not a Python programmer. Does this work around urllib2 require amends wherever script is connecting or I can do it only once? – Michal Pietras May 21 '11 at 13:12
  • The code given patches urllib2. After execution, all subsequent calls will benefit from the patch. – Jerome May 25 '11 at 08:43
0

You can set the outgoing IP address with out editing the python source code simply by executing the code described here as a string in the interpreter before running the embedded code. Something like this would work:

#include <Python.h>

int main(int argc, char *argv[]) {
  Py_SetProgramName(argv[0]);
  Py_Initialize();
  PyRun_SimpleString
    ("import socket\n"
     "true_socket = socket.socket\n"
     "def bound_socket(*a, **k):\n"
     "    sock = true_socket(*a, **k)\n"
     "    sock.bind((127.0.0.1, 0))\n"
     "    return sock\n"
     "socket.socket = bound_socket\n");

  // Run embedded code here

  Py_Finalize();
  return 0;
}

Of course you would replace 127.0.0.1 with the correct source IP address.

Community
  • 1
  • 1
jcoffland
  • 5,238
  • 38
  • 43