31.6 C
Jaipur
Tuesday, September 21, 2021

How to find and replace ALL IP addresses with a new one

Must read

At a certain point, I needed to change the VLAN IP address such as 172.0.0.2 with 172.0.0.1 for ease of use. As you know, Linux and Unix-like operating system stores all IP addresses and config in plain text files. This page explains my little adventure where I had to find and find and replace ALL IP addresses with a new one on Linux.

Tutorial details
Difficulty level Easy
Root privileges Yes
Requirements grep, sed, and Bash
Est. reading time 5 minutes

WARNING! I am dealing with system files stored at /etc/. Hence, root access is necessary. I also made snapshots option provided by Linode and backups before I decided to automate it. I am using Linode, but the procedure remains the same regardless of the home or cloud service provider. The important thing is to make a backup to recover in case something went wrong during mass editing.

Making Linode Server Backup

I made a manual backup of my Linode server by taking a snapshot

Step 1 – Finding a list of files for the old IP address

I decided to use the grep command as follows:
grep -R -w '172.0.0.2' /etc/
A truncated list of files that needs updating:

/etc/keepalived/keepalived.conf:    unicast_src_ip  172.0.0.2 # Private IP address of master (redis1)
/etc/ufw/user.rules:### tuple ### allow tcp 6379 172.0.0.2 any 172.0.0.0/24 in_eth1 comment=4f70656e2054435020526564697320504f5254206f6e2072656469733120686f737420666f7220636c7573746572
/etc/ufw/user.rules:-A ufw-user-input -i eth1 -p tcp -d 172.0.0.2 --dport 6379 -s 172.0.0.0/24 -j ACCEPT
/etc/ufw/user.rules:### tuple ### allow tcp 26379 172.0.0.2 any 172.0.0.0/24 in_eth1 comment=4f70656e205443502053454e5449454c20504f5254206f6e2072656469733120686f737420666f7220636c7573746572
/etc/ufw/user.rules:-A ufw-user-input -i eth1 -p tcp -d 172.0.0.2 --dport 26379 -s 172.0.0.0/24 -j ACCEPT
/etc/systemd/network/.05-eth1.network.linode-last:Address=172.0.0.2/24
/etc/systemd/network/.05-eth1.network.linode-orig:Address=172.0.0.2/24
/etc/haproxy/haproxy.cfg:# redis1 - 172.0.0.2
/etc/haproxy/haproxy.cfg:        server redis2 172.0.0.2:6379 check inter 3s
/etc/hosts:172.0.0.2	redis1 haproxy1 keepalived1
/etc/redis/sentinel.conf:bind 172.0.0.2
/etc/redis/sentinel.conf:sentinel known-replica mymaster 172.0.0.2 6379
/etc/redis/redis.conf:bind 172.0.0.2
.....
..
.....

I need to update services such as HAProxy, Nginx, Redis, MySQL, firewall rules, and more. The -R option read all files under each directory, recursively. It will also follow all symbolic links. The -w option will tell grep to select only those lines containing matches that form whole word.

Step 2 – Finding and replacing ip address with a new one using sed

This task is pretty simple, and the syntax for sed is as follows:
sed -i'.BACKUP' 's/OLD_IP_HERE/NEW_IP_HERE/g' input
For example:

Patreon supporters only guides 🤓

  • No ads and tracking
  • In-depth guides for developers and sysadmins at Opensourceflare
  • Join my Patreon to support independent content creators and start reading latest guides:

Join Patreon

OLD_IP='172.0.0.2'
NEW_IP='172.0.0.1'
INPUT_FILE='/etc/redis/redis.conf'
sed -i'.BACKUP' "s/${OLD_IP}/${NEW_IP}/g" "${INPUT_FILE}"

The -i option tells sed to make a backup before updating file. I can verify using the diff command:
diff /etc/redis/redis.conf /etc/redis/redis.conf.BACKUP
I compared updated file /etc/redis/redis.conf line-by-line with original backup file named /etc/redis/redis.conf.BACKUP:

70c70
< bind 172.0.0.1
---
> bind 172.0.0.2

Step 3 – Shell script to find and replace ALL IP addresses

First, we need to update the grep command as follows to get a list of files:
grep -l -H -R -w '172.0.0.2' /etc/
Outputs:

/etc/keepalived/keepalived.conf
/etc/ufw/user.rules
/etc/systemd/network/.05-eth1.network.linode-last
/etc/systemd/network/.05-eth1.network.linode-orig
/etc/haproxy/haproxy.cfg
/etc/hosts
/etc/redis/sentinel.conf
/etc/nginx/http.d/cyberciti.biz.conf
/etc/mysql/my.cnf

The -l option is most important for mass editing as it will suppress standard output. Instead, grep will print the name of each input file from which output would normally have been printed. The -H options ensure that grep displays each match’s file name. Then I am going to feed this list to sed using a while loop or bash for loop:

#!/bin/bash
set -euxo pipefail
OLD_IP='172.0.0.2'	# old server ip
NEW_IP='172.0.0.1'	# new server ip
DEST_DIR="/etc"		# search dir 
 
# Get file list
INPUT_FILES="$(grep -l -H -R -w ${OLD_IP} $DEST_DIR)"
 
# Ignore following dirs and files 
IGNORE_PATHS=(/etc/systemd/network/ /etc/network/ /etc/networks /etc/keepalived/keepalived.conf)
is_skip=0
 
# main
for f in $INPUT_FILES 
do
	for i in "${IGNORE_PATHS[@]}"
	do
		if [[ $f == *"${i}"* ]]
		then
			is_skip=1
			continue
		fi
	done
	[ $is_skip == 0  ] && sed -i'.BACKUP' "s/${OLD_IP}/${NEW_IP}/g" "$f"
	is_skip=0
done

After running the script, restart those services one by one using the systemctl command. For example:
sudo systemctl restart haproxy.service

Summing up

For Ansible, you need to edit the script to detect hostname and set correct OLD_IP and NEW_IP for each host. It can be done quickly using Bash array and case statement in the Bash script itself and left as an exercise to readers.

That was an easy and fun thing to do. For multiple servers, we can use Ansible to do our dirty work. The logic remains same or we can use above script:

---
- hosts: mylinodeservers
  tasks:

      - name: Copy IP update script
        ansible.builtin.copy:
          src: ip.updates.sh
          dest: ~/ip.updates.sh
          mode: 0700

      - name: Run ip.update.sh script
        command:~/ip.updates.sh

Update or edit the hosts file:

[mylinodeservers]
linode-01 ansible_user=admin ansible_python_interpreter='/usr/bin/python3'
linode-02 ansible_user=admin ansible_python_interpreter='/usr/bin/python3' 
linode-03 ansible_user=admin ansible_python_interpreter='/usr/bin/python3'

Then run it as follows:

ansible-playbook -i hosts --ask-vault-pass linode.yaml
# get other data from '@linode.data.yml' 
ansible-playbook -i hosts --ask-vault-pass --extra-vars '@linode.data.yml'  linode.yaml

See “How to find and replace text/IP address with Ansible” for other options. Make sure you read bash and other man pages for more information using the man command:
man bash
man sed
man grep


ADVERTISEMENT

Source link

- Advertisement -

More articles

LEAVE A REPLY

Please enter your comment!
Please enter your name here

- Advertisement -

Latest article