Check ip is present within file & update iptables bash script - bash

I want to check that the ip is present within the ccd folder and push the ip route to the FORWARDING chain in the iptables. Im new to bash scripting and need a little help finishing this script.
client file in /etc/openvpn/ccd :
ifconfig-push 10.8.0.45 255.255.255.0
push 'route 10.10.0.45'
I need to grep 10.8.0.45 & 10.10.0.45
and push those routes in the iptables.
e.g
iptables -A FORWARD -s 10.8.0.45 -d 10.10.0.45 -j ACCEPT
client-connect /etc/openvpn/on_connect.sh
script I need help with 'grep' or 'awk'
static_ip= cat $CCD_DIR/$common_name | grep -w "ifconfig-push" | awk -F ' ' {'print $2'}
ip_destination=cat $CCD_DIR/$common_name | grep -w "push 'route" | awk -F ' ' {'print $3'} | tr -d "'"
#!/usr/bin/env bash
#
# Add iptables rules based on CCD client config.
#
CCD_DIR="/etc/openvpn/ccd"
RULE_COMMENT="FORWARD"$common_name
static_ip=cat $CCD_DIR/$common_name | grep -w "ifconfig-push" | awk -F ' ' {'print $2'}.
ip_destination=cat $CCD_DIR/$common_name | grep -w "push 'route" | awk -F ' ' {'print $3'} | tr -d "'"
if [ -f $CCD_DIR/$common_name ]; then
sudo iptables -A FORWARD -s $static_ip -d ip_destination -j ACCEPT
fi
exit 0
Edit: I think my usage of cat is wrong .

Try like this.
static_ip=$( cat $CCD_DIR | grep -oE "\b([0-9]{1,3}\.){3}[0-9]{1,3}\b" | grep -E '(^|\s)10.8.0.45($|\s)' )
ip_destination=$( cat $CCD_DIR | grep -oE "\b([0-9]{1,3}\.){3}[0-9]{1,3}\b" | grep -E '(^|\s)10.10.0.45($|\s)' )
So first you grep all IP's address in file and then you search exactly what you need
Edited after your comment.
If I understand correctly,
"ifconfig-push" - Is only one peer ccd file ?
so you can use this :
static_ip=$( grep -w "ifconfig-push" | awk -F ' ' {'print $2'})
For the rest in "push route" you need to use loop to find all matching ip address and put them to the iptables.
if [ -f $CCD_DIR/$common_name ]
then
cat $CCD_DIR | awk -F 'route' {'print $2'} | awk -F ' ' {'print $1'} | sed '/^$/d' | grep -E "\b(10)\.(8)\.(0)\.|(10)\.(10)\.(0).\b" | while read ip_destination
do
sudo iptables -A FORWARD -s $static_ip -d ip_destination -j ACCEPT
done
fi

Related

How to pass output to Ping as stdin

I have this command to strip the https:// portion and truncate the ending /.
echo https://example.com/ | awk -F '//' {'print $2'} | tr -d '/'
How can I pass the output to ping or host command as a stdin, making it an oneliner?
example.com
The expected output is the result of host/ping example.com
I have tried below commands
echo https://example.com/ | awk -F '//' {'print $2'} | tr -d '/' | ping $
echo https://example.com/ | awk -F '//' {'print $2'} | tr -d '/' | ping $1
I never got the expected results.
I found the answer, it can be achieved by piping using xargs
echo https://example.com/ | awk -F '//' {'print $2'} | tr -d '/' | xargs ping
echo https://example.com/ | awk -F '//' {'print $2'} | tr -d '/' | xargs host
You could try this:
echo https://example.com/ |(IFS=/ read http nothing host; ping $host)
IFS splits the reading at the slash character; the parenthesis are needed for read to work. If you just need the ping the above command is ok. Or, you can extract the host name:
host=$(echo https://example.com/ |(IFS=/ read http nothing host; echo $host))
ping $host

grep search with filename as parameter

I'm working on a shell script.
OUT=$1
here, the OUT variable is my filename.
I'm using grep search as follows:
l=`grep "$pattern " -A 15 $OUT | grep -w $i | awk '{print $8}'|tail -1 | tr '\n' ','`
The issue is that the filename parameter I must pass is test.log.However, I have the folder structure :
test.log
test.log.001
test.log.002
I would ideally like to pass the filename as test.log and would like it to search it in all log files.I know the usual way to do is by using test.log.* in command line, but I'm facing difficulty replicating the same in shell script.
My efforts:
var-$'.*'
l=`grep "$pattern " -A 15 $OUT$var | grep -w $i | awk '{print $8}'|tail -1 | tr '\n' ','`
However, I did not get the desired result.
Hopefully this will get you closer:
#!/bin/bash
for f in "${1}*"; do
grep "$pattern" -A15 "$f"
done | grep -w $i | awk 'END{print $8}'

Bash script any reason why it wont write the file

I am helping debug some code that exec the following script is there any reason why its not writing a file to the server? - if that what it does. All the $ data and permissions are ok:
Script:
#!/bin/bash
RANGE=$1
ALLOCATION=`echo $RANGE | cut -f1,2,3 -d'.'`
/sbin/ip rule add from $1 lookup $2
echo $ALLOCATION
rm /path/too/file/location/$ALLOCATION
for i in `seq 3 254`
do
echo $ALLOCATION.$i >> /path/too/file/location/$ALLOCATION
done
ETH=`/sbin/ifconfig | grep eth0 | tail -n1 | cut -f2 -d':' | cut -f1 -d' '`

Bash output to multiple variales

I'm creating a script in Bash to change all MAC addresses of my PC. I can list all network interfaces with this:
ip link | grep "<" | cut -d " " -f 2 | cut -d ":" -f 1 | grep -v lo
And the output of the script is:
eth0
wlan0
Now I need to create a variable for each network interface (to use it in the future), but I don't know how, and Google didn't help me...
Answer:
readarray -t interfaces < <(ip link | grep "<" | cut -d " " -f 2 | cut -d ":" -f 1 | grep -v lo)
echo "${interfaces[0]}" # prints eth0
echo "${interfaces[1]}" # prints wlan0
And to loop over them use for:
for curInterface in "${interfaces[#]}"; do
echo "$curInterface"
done
But there are better ways to parse data:
First of all, instead of grepping < character you can use -o flag. This will output all of the data on single lines. Then you simply need the second word without : character. This is very simple in pure bash:
interfaces=()
while read -r _ curInterface _; do
interfaces+=("${curInterface%:}")
done < <(ip -o link)
Store the output in an array:
interfaces=( $(ip link | awk '/</ { print $2 }' | awk -F: '!/lo/ {print $1}') )
You can create an array from this output, and loop through it after.
my_array=( $(ip link | grep "<" | cut -d " " -f 2 | cut -d ":" -f 1 | grep -v lo) )
You can also this exmaple giving different alternatives redirect output to array
And I could have it simpler like this with one awk command:
readarray -t youravar < <(exec ip link | awk -F': ' '/^[0-9]+:/&&!/ lo: /{print $2}')

Bash new variable with other variable

I get the ip address like that :
Ip=`ifconfig | grep inet | grep -v -E 'inet6|127.0.0.1' | \
tr -d [:alpha:] | tr -s [:space:] | cut -d: -f2`
I have an ip like this for instance : 10.1.0.76
I want to make a new variable with the Ip variable to have another ip, for instance my new variable will return : 10.1.0.178
Just the last number change, so I want to get just a part of Ip variable (10.1.0.) and add another number to the end.
I tried with sed but I always have mistakes like "there's no file call'd ..."
Can you help me ?
You can use parameter expansion: It's simply: ${Ip%.*}.178
${Ip%.*} is the ip with the last dot and everything after it removed. The .178 is what you want to append after that.
Here it is in context:
# Your original expression
Ip=`ifconfig | grep inet | grep -v -E 'inet6|127.0.0.1' | \
tr -d [:alpha:] | tr -s [:space:] | cut -d: -f2`
# assign a new variable with the ip with different end octet
newIp=${Ip%.*}.178
# Show new ip
echo "$newIp"
Well, given that you have IP in a format x.y.z.w, you can use perl regex:
$ echo "120.20.31.78" | perl -pe 's/(.*)\..*/$1\.123/'
120.20.31.123
This will repace last number ("78") with "123".
So, in your case (assuming your "Ip" variable is set correctly), it would be:
Ip=ifconfig | grep inet | grep -v -E 'inet6|127.0.0.1' | tr -d [:alpha:] | tr -s [:space:] | cut -d: -f2 | perl -pe 's/(.*)\..*/$1\.123/'
see this, I hope it is what you want:
kent$ echo $ip
10.1.0.76
kent$ echo $part
178
kent$ sed -r "s/(.*\.).*/\1$part/" <<< $ip
10.1.0.178
to set $ip with new value:
kent$ ip=$(sed -r "s/(.*\.).*/\1$part/" <<< $ip)
kent$ echo $ip
10.1.0.178

Resources