On boot, how can I switch to a static IP based on a gateway IP provided by DHCP?

2

1

I have a "headless" *NIX host -- let's call it 'foo' -- that is to be accessible via SSH and VNC-tunneled-over-SSH on an arbitrary 192.168.x.y/24 private LAN. Sometimes, I want to physically move 'foo' from one LAN to another, so 'x' depends on the LAN, and I want 'y' to be constant, with an ordered list of alternatives to handle allocation contention.

So although I want a static address ( to target with SSH ), I also need it to be dynamic ( to match the subnet of the LAN it has been attached to ).

Yes, some routers allow "special sauce" like DHCP reservation or additional routing configuration, but let's say that I don't have access to the router, but I can expect it to provide DHCP.

So, if I were to do this manually, I would set 'foo' up to use DHCP on boot, and once I get a shell, I can look at the gateway address to figure out my subnet, 192.168.x.0, where 'x' is what varies from one LAN to another; then I would edit '/etc/network/interfaces' ( or equivalent ) to switch from DHCP to static, synthesizing the address from 'x' and the constant 'y' ( first pinging 192.168.x.y to check if it's occupied and if so, choosing the next 'y' from a list of pre-defined choices, so in less optimal situations, I might have to try several addresses when I run SSH ), and then restarting the networking service.

A trickier variation would be a LAN that lacks DHCP; in that case, the subnet could probably be guessed by sampling some LAN traffic.

If such a setup could be automated, then 'foo' could simply be attached to an arbitrary LAN and booted, and there would be a good chance of finding its IP address first try.

Are there any clever ways to do what I'm after?

Remember, all configuration must be done on host 'foo', and the only assumption that can be made about the target LAN to which it is attached is that it uses a 192.168.x.y/24 private subnet.

bernz

Posted 2015-04-09T18:32:06.823

Reputation: 178

you will have to leave it as DHCP. and run a script to analyze the gateway provided and then change the address. the tricky part will be making sure its set back to DHCP for the next boot, or the whole thing would call apart. The script itself would be OS dependent. its pretty easy to modify the /etc/network/interfaces file and restart the networking service on linux from a script, and windows has netsh and WMI that could do it. – Frank Thomas – 2015-04-09T18:36:24.827

Frank, right, this is *NIX-only, I've edited the question to reflect that. But yeah, it sounds like I have to cook up my own solution; I thought there might already exist a tool to do something like this.

Is there a way to force '/etc/network/interfaces' to start from a "template" ( so it always boots with DHCP )...? – bernz – 2015-04-09T18:38:34.933

don't forget when you connect this ... um, shall we say "lurking" device ... into the ... ah, "foreign" network, your assumption of an IP range of 192.168 is inadequate. it could be 10, 10.1, 10.0.1, ... you get the drift. However it's no more difficult than your example. – Daniel – 2015-04-09T18:39:10.647

@bernz ... PM me if you want me to write this script for you. – Daniel – 2015-04-09T18:40:27.143

Thanks Daniel, agreed. In my use case, it's a RasPi that I want to drag between home and work -- not for anything nefarious, mind you ;-) -- and both networks are using 192.168.x.y private subnets.

@Daniel, sorry, I'm a in novice mode here... there doesn't appear to be a PM feature for StackExchange... if you don't mind posting the script here, though, that'd be appreciated. :-) – bernz – 2015-04-09T18:41:00.347

I'll write it when I get home tonight. – Daniel – 2015-04-09T18:46:45.493

Answers

1

Some bugs probably, but should be enough to do what's needed.

run as root.


#!/bin/bash

ARPCOUNT=10
LOCALNET=`route | grep default | awk '{print $2}' | cut -f1-3 -d'.'`
NETMASK=`route | grep default | awk '{print $3}'`
DEVICE=`route | grep default | awk '{print $8}'`

for ((xval=100; xval<254; xval++ )) ; do

    CURIP=$LOCALNET.$xval

    arping -c $ARPCOUNT $CURIP > /dev/null
    ARPRESULT=$?

    if ! [ $ARPRESULT ] ; then
    echo "No IP found at $CURIP."

    else
    route
    ifconfig $DEVICE down
    ifconfig $DEVICE $LOCALNET.$xval netmask $NETMASK
    ifconfig $DEVICE up
    route
    echo "Changed to IP $CURIP."
    exit
    fi

done

Daniel

Posted 2015-04-09T18:32:06.823

Reputation: 932

Thanks, this looks like a great start; I will learn from and hack on it until it's working for my device. – bernz – 2015-04-10T12:56:12.613

you should add some tags kind linux, ubuntu to question. firstly i falled to windows netsh script – Yurij – 2019-08-14T09:59:23.467

@Yurij thanks for the comment, but I can't understand what your wrote. Perhaps try improving the grammar and adding additional sentences to complete the thoughts. – Daniel – 2019-08-14T17:25:13.377