2

I am editting/extending my firewall bash script on ubuntu dedicated server.

The code below is just an excerpt. The purpose below is to reroute/open for some IPs my (http, ftp, telnet and ssh) ports for/to 3 boxes.

The problem is that I want to use variables in a variable. So --dport ${i}_${j}_port_ext is correctly replaced by f.i. --dport box0_http_port_ext but is not seen as a variable (of course). Actually, what I want should be --dport $box0_http_port_ext (mind the $ at the beginning)

I tried several things f.i. --dport ${${i}_${j}_port_ext} or --dport $(${i}_${j}_port_ext) but that is not good.

box0_http_port_ext="8080"
box0_ftp_port_ext="21"
box0_telnet_port_ext="23"
box0_ssh_port_ext="22"
#
allow_box0_http_port_ip="1.2.3.4 99.98.97.96 55.56.57.58"
allow_box0_ftp_port_ip="1.2.3.4 55.56.57.58"
allow_box0_telnet_port_ip="55.56.57.58"
allow_box0_ssh_port_ip="1.2.3.4"
#
for i in box0 box1 box2
do
  for j in http ftp telnet ssh
  do   
    for ips in $allow_${i}_${j}_port_ip
    do
      $IPTABLES -t nat -A PREROUTING -p tcp -i $LAN_IFACE -s $ips --dport ${i}_${j}_port_ext -j DNAT --to-destination ${i}_ip:${i}_${j}_port_int
    done
  done
done

Please do not look at the code because it is an excerpt and thus not complete.
The question is: how to code --dport $box0_http_port_ext by making use of $i for box0 and $j for http. Keeping in mind that $i also can be box1/box2 and $j also can be replaced by ftp/telnet/ssh.

1
  • @ni_hao please share the solution once you got it fixed. Commented Feb 13, 2013 at 7:44

4 Answers 4

5

You can do it using an Indirect Variable Reference (See http://tldp.org/LDP/abs/html/bashver2.html#EX78)

This is available in Bash Version 2 and above, using a ! before the variable name, inside the ${ }.

name=${i}_${j}_port_ext
echo ${!name}

Working example:

#!/bin/bash
i=box0
j=http

box0_http_port_ext="hello1"
box2_telnet_port_ext="hello2"

name=${i}_${j}_port_ext
echo "varname: $name   value: ${!name}"

i="box2"
j="telnet"
name="${i}_${j}_port_ext"
echo "varname: $name   value: ${!name}"

Output:

varname: box0_http_port_ext   value: hello1
varname: box2_telnet_port_ext   value: hello2

In the above example $name returns the sting box0_http_port_ext, which is the name of the initial variable. This is equivalent to ${name}. The ! operator evaluates the string to its right side as a variable name, and returns the value that is stored in the variable. So ${!name} returns the value of ${box0_http_port_ext} which is hello1.

Unfortunately bash does not support multi-dimensional arrays, but this trick can be used instead.

The difference from the other answer is that $i_$j_port_ext is changed to ${i}_${j}_port_ext so that bash knows where the name of the variable ends.

Sign up to request clarification or add additional context in comments.

Comments

2

Try this:

varname=${i}_${j}_port_ext
... --dport ${!varname} ...

Note the ! inside the ${}

Edited: good point from @user000001 about delimiting the i/j variable names.

Comments

0

Please try to escape _ character in the script

--dport $i\_$j\_port\_ext

Comments

0

thanks you helped me a lot.

BTW, I did notice the difference between f.i. $name and {!name}. $name gives the name of the variable, where ${!name} the contents of the variable gives. Is that the only explanation?

Regarding the (good) comments to my question i.r.t. the above mentioned excerpt, this is working for me:

for i in box0 box1 box2
do
  for j in http ftp telnet ssh
  do
    ALLOWED_IPS=allow_${i}_${j}_port_ip
    for ips in ${!ALLOWED_IPS}; do
    do
      PORT_EXT=${i}_${j}_port_ext; PORT_INT=${i}_${j}_port_int; IP=${i}_ip
      $IPTABLES -t nat -A PREROUTING -p tcp -i $LAN_IFACE -s $ips --dport ${!PORT_EXT} -j DNAT --to-destination ${!IP}:${!PORT_INT}
    done
  done
done

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.