Assume you have an application that is bound to a machine with a certain hostname, MAC address or hostid. If this machine shall be replaced and you don't want to setup a new (virtual) machine just for this application, you can follow these explanations to start this application in a light-weight container using library preloading and Linux namespaces on an arbitrary machine.
The script and source code can also be found in my Github repository.
To pretend a certain MAC address or hostname, we can use Linux namespaces and create a virtual ethernet device with the required MAC and set an arbitrary hostname without disrupting the operation of other processes. New namespaces for a child process can be created with the unshare command. In this case we create a new network and UTS namespace:
unshare -n -u <child_command>
Afterwards we create a pair of virtual ethernet (host0 and guest0) devices with:
ip link add name host0 type veth peer name guest0
To move the guest0 interface into the new namespace we use the following command:
ip link set guest0 netns $pid_of_child_cmd
In the following, we can set custom IP and MAC addresses on both interfaces.
In order to modify hostname resolution, we build a library that intercepts calls to the libc. The resolution is done by the gethostbyname function. Therefore, we create the following function that first gets the address of the real gethostbyname in libc and then returns either the resolution of "newhost" in case the application requests "oldhost" or the real host for all other names.
struct hostent * gethostbyname(const char *name) {
if (!real_gethostbyname) {
real_gethostbyname = dlsym(RTLD_NEXT, "gethostbyname");
}
if (!strcmp(name, "oldhost")) {
return real_gethostbyname("newhost");
} else {
return real_gethostbyname(name);
}
}
To use this library, we have to call our application in the following way:
LD_PRELOAD=/path/to/libinject.so myapplication
If the application offers services over the network, one can use well-known port forwarding mechanisms in the host namespace, e.g., iptables or socat.