Help needed writing a script

Status
Not open for further replies.
Joined
Mar 6, 2014
Messages
686
Joined
Mar 6, 2014
Messages
686
*sigh*.... it doesn't work when starting the jail, it doesn't add the four variable rules. If i manually restart the firewall, everythin works fine. it adds the rules when the VPN connection comes up before the 5 retries, else, it adds only the fixed ruls. But when sthe jail starts up, it doesn't add the variable rules. Why is the script handled differently at jail startup?
 

joeschmuck

Old Man
Moderator
Joined
May 28, 2011
Messages
10,970
I guess I'm lost with what you are saying... You lost me when you said "If i manually restart the firewall, everythin works fine."

Are you saying that when you start the jail up, the script doesn't appear to run?

Something you could do to verify the script runs when the jail starts is to have it create a file. Just make sure you delete it before stopping the jail and starting it up again.

In your script add:
Code:
echo "This is a test" > /temp.txt

Now when you restart the jail it should create a file called temp.txt at the root directory level. Of course you can place it anywhere you desire but I often do crazy little things like this when developing scripts. I also use a lot of REM statements describing exactly what I am expecting to do. This helps 6 months or so down the road when I want to make a new script and I can use the old one as an example.
 
Joined
Mar 6, 2014
Messages
686
The script works only partially when the jail starts up. Rules are flushed, then the "fixed" rules in the script are added, but rules 500# are not loaded. So the script runs on startup, it just doesn't work as expected, not the same as running it manually. Not even if i set the sleep time and counter to 10x10 seconds. The added rules can easily be checked with "ipfw list". When i start things maually, it works fine in these scenarios:

Preconditions: firewall not running & VPN not running.
  1. Start firewall.... Counts until 5, then adds alle rules, except the 500# range ==> as expected
  2. Start firewall.... Counts to 1...2... Manually start OpenVPN from other shell... still counting: 3....(4....) adds all rules, including 500# range ==> as expected
So now i am lost......
 

joeschmuck

Old Man
Moderator
Joined
May 28, 2011
Messages
10,970
How are you starting the script(s) (give exact details)?

So you start the jail and you have what start first, then what happens? Getting things in a jail to work the way you want them to can be tricky.
 
Joined
Mar 6, 2014
Messages
686
When the jail start, the script gets called in /etc/rc.conf:
Code:
openvpn_enable="YES"
openvpn_configfile="/usr/local/etc/openvpn/openvpn.conf"
firewall_enable="YES"
firewall_script="/mnt/media/ipfw.rules"


When i start the firewall manually, i use /etc/rc.d/ipfw (re)start

What happens, is what i described in my previous post. I really don't get why the script is handled differently.
 

jgreco

Resident Grinch
Joined
May 29, 2011
Messages
18,681
When the jail start, the script gets called in /etc/rc.conf:
Code:
openvpn_enable="YES"
openvpn_configfile="/usr/local/etc/openvpn/openvpn.conf"
firewall_enable="YES"
firewall_script="/mnt/media/ipfw.rules"


When i start the firewall manually, i use /etc/rc.d/ipfw (re)start

What happens, is what i described in my previous post. I really don't get why the script is handled differently.

The usual reason is a poorly written script, often something like the environment. For example, ipfw is in /sbin/, so if you aren't setting up your PATH explicitly in the script or calling it by fully qualified path, it's a crapshoot as to whether or not your command ends up in that sometimes-omitted directory.

A shell script, especially for beginners, probably ought to start off:

Code:
#! /bin/sh -

PATH=/bin:/usr/bin:/usr/local/bin:/sbin:/usr/sbin; export PATH

set -e


A more complex version might include a trap to spit out an error message.

You could follow this up with some error logging:

Code:
(
       your-stuff-in-here
) >> /tmp/myscript.out 2>> /tmp/myscript.err


which will put uncaptured/unhandled output into those two files.

And when I say "poorly written," don't take offense - shell script is a wonderful thing but it takes years to master. I've been doing it for several decades and I'm not even all that great at it.
 

jgreco

Resident Grinch
Joined
May 29, 2011
Messages
18,681
I think i get it:
Code:
IP1="ifconfig | grep 'vpn' | cut -d" " -f4"
add 05000 allow ip from ${IP1} to any

Going to test some stuff when i get home :)

EDIT: Not sure if that will work, seeing all the " marks in the first line....

By the way, what happens if there are two devices matching "vpn"? Use "grep -m 1" and maybe a better ifconfig incantation to help more precisely aim your data acquisition.
 
Joined
Mar 6, 2014
Messages
686
Hi guys, not offended what so ever :)
I KNOW i'm just starting off, so all criticism is actually very welcome.

By the way, what happens if there are two devices matching "vpn"? Use "grep -m 1" and maybe a better ifconfig incantation to help more precisely aim your data acquisition.
I can only have 1 VPN connection, just connection to 1 server / 1 IP at a time as far as i know, but i'll be sure to try out what you suggested

... often something like the environment. For example, ipfw is in /sbin/, so if you aren't setting up your PATH explicitly in the script or calling it by fully qualified path, it's a crapshoot as to whether or not your command ends up in that sometimes-omitted directory.
As you can see, i only use complete paths in my script, so i don't think that's the problem. Here is my script so far:
Code:
#!/bin/sh

fwcmd="/sbin/ipfw"
${fwcmd} -f flush

IP2="$(/sbin/ifconfig | grep 'inet 10' | cut -d" " -f4)"
n=0
echo "${n}" + "${IP2}" > /mnt/media/ipfwscript.log

until [ "$IP2" != "" ] || [ $n -ge 10 ]
do
    sleep 5 
    IP2="$(/sbin/ifconfig | grep 'inet 10' | cut -d" " -f4)"
    let n=$n+1 
    echo "${n}" + "${IP2}" >> /mnt/media/ipfwscript.log
done

IP1="$(/sbin/ifconfig | grep 'inet 10' | cut -d" " -f2)"
echo "${n}" + "${IP1}" >> /mnt/media/ipfwscript.log

${fwcmd} add 01000 allow log udp from 192.168.2.0/24 to xxx.xxx.xxx.xxx dst-port 53 keep-state
${fwcmd} add 01002 allow log udp from 192.168.2.0/24 to xxx.xxx.xxx.xxx dst-port 53 keep-state
${fwcmd} add 01006 allow ip from 192.168.2.0/24 to 192.168.2.0/24 keep-state
${fwcmd} add 02000 allow ip from 192.168.2.0/24 to xxx.xxx.xxx.xxx keep-state
${fwcmd} add 04000 allow ip from 127.0.0.1 to any
${fwcmd} add 05000 allow ip from "${IP1}" to any
${fwcmd} add 05002 allow ip from any to "${IP1}"
${fwcmd} add 05004 allow ip from "${IP2}" to any
${fwcmd} add 05006 allow ip from any to "${IP2}"
${fwcmd} add 65534 deny ip from any to any


When i call it manually, results as in post 24
Output file in scenario 2:
Code:
0 +
1 +
2 +
3 + xxx.xxx.xx1
3 + xxx.xxx.xx2

So that is all fine :)

When started at jail startup, output file:
Code:
0 +
1 +
2 +
3 +
4 +
5 +
6 +
7 +
8 +
9 +
10 +
10 + 

So....not so fine :(
 

jgreco

Resident Grinch
Joined
May 29, 2011
Messages
18,681
Grep, cut, sleep ... not complete paths. echo is arguably a shell built-in so you don't lose points there.

Try using the structure I provided to catch stdout/err instead of all the echo-to-files. Then you can also make use of "set -x" and/or "set -v" to easily get an idea of exactly what is happening in the script.

There's LOTS of room for improvement in this script. For example, if you consider inet 10, what happens when you get assigned a public IP address with a first octet of 100 through 109?

Again, no worries, I am happy to point out whatever little things I happened to notice.
 
Joined
Mar 6, 2014
Messages
686
Well, i tried everything you said, path, log, get rid of the echo stuff....still the same result. error log is empty, output file shows the same as a it had with the echo stuff.

Script:
Code:
#!/bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin; export PATH
set -e

(
#set -x

fwcmd="/sbin/ipfw"
${fwcmd} -f flush

IP2="$(/sbin/ifconfig | grep 'inet 10.' | cut -d" " -f4)"
n=0

until [ "$IP2" != "" ] || [ $n -ge 5 ]
do
    sleep 5
    IP2="$(/sbin/ifconfig | grep 'inet 10.' | cut -d" " -f4)"
    let n=$n+1
done

IP1="$(/sbin/ifconfig | grep 'inet 10.' | cut -d" " -f2)"

${fwcmd} add 01000 allow log udp from 192.168.2.0/24 to xxx.xxx.xxx.xxx dst-port 53 keep-state
${fwcmd} add 01002 allow log udp from 192.168.2.0/24 to xxx.xxx.xxx.xxx dst-port 53 keep-state
${fwcmd} add 01006 allow ip from 192.168.2.0/24 to 192.168.2.0/24 keep-state
${fwcmd} add 02000 allow ip from 192.168.2.0/24 to xxx.xxx.xxx.xxx keep-state
${fwcmd} add 04000 allow ip from 127.0.0.1 to any
if [ "$IP2" != "" ]; then
    ${fwcmd} add 05000 allow ip from "${IP1}" to any
fi
if [ "$IP2" != "" ]; then
    ${fwcmd} add 05002 allow ip from any to "${IP1}"
fi
if [ "$IP2" != "" ]; then
    ${fwcmd} add 05004 allow ip from "${IP2}" to any
fi
if [ "$IP2" != "" ]; then
    ${fwcmd} add 05006 allow ip from any to "${IP2}"
fi
${fwcmd} add 65534 deny ip from any to any

#set +x
) > /mnt/media/script.out 2> /mnt/media/script.err

(also fixed the 'inet 10' "problem", by changing it to 'inet 10.' on line 11, 17 & 21

Output file:
Code:
Flushed all rules.
1
2
3
4
5
01000 allow log udp from 192.168.2.0/24 to xxx.xxx.xxx.xxx dst-port 53 keep-state
01002 allow log udp from 192.168.2.0/24 to xxx.xxx.xxx.xxx dst-port 53 keep-state
01006 allow ip from 192.168.2.0/24 to 192.168.2.0/24 keep-state
02000 allow ip from 192.168.2.0/24 to xxx.xxx.xxx.xxx keep-state
04000 allow ip from 127.0.0.1 to any
65534 deny ip from any to any
 
Last edited:

joeschmuck

Old Man
Moderator
Joined
May 28, 2011
Messages
10,970
As far as I know your issue has nothing to do with the way you wrote this script and everything to do with what starts first, second, third. I have run into this kind of stuff a lot while playing with jails and I would recommend you take a different approach here.

You need to understand how you are starting up your applications... rc.conf will kick off your applications but it doesn't wait for one to complete before starting another one. I believe the issue is OpenVPN isn't started when your kicking off your firewall rules script.

Recommendation: Kick off your firewall script using a crob job and make it run every say 1 minute (I don't know how frequent you would really want this to be checked). If this works then rewrite the script to check if there is a change and only apply the rules if a change exists. To test the script you would need to make some changes to fake out the IP address change but that is easy to do. Do not worry about making it look pretty, just make it work first. If I have a similar setup then I could give you more assistance but I don't. Optimum would be if OpenVPN would do something after it is started up to trigger the firewall script.
 
Joined
Mar 6, 2014
Messages
686
Strange... If you look at the lines, OpenVPN is started before the firewall, or at least this comes first in rc.conf.

Maybe i should be looking into scheduling a cron job. I have no idea on how OpenVPN could be the trigger somehow. If there is a way however, OpenVPN might also be a trigger i could use to run a script when the config (IP) would change. Much cleaner way i think then a timed schedule. I would rather have an actual change trigger the script, not some job running constantly (or periodically). Also less down time, depending on the cron schedele. The latter is not that important for me, but still....

Anyway, more thing for me to look into. Thanks again so far
 

jgreco

Resident Grinch
Joined
May 29, 2011
Messages
18,681
rc.conf will kick off your applications but it doesn't wait for one to complete before starting another one. I believe the issue is OpenVPN isn't started when your kicking off your firewall rules script.

rc.conf doesn't kick off applications. It is technically a shell script but its role in life is to be a place to set variables for the rc subsystem.

Strange... If you look at the lines, OpenVPN is started before the firewall, or at least this comes first in rc.conf.

See immediately preceding comment.

Maybe i should be looking into scheduling a cron job. I have no idea on how OpenVPN could be the trigger somehow. If there is a way however, OpenVPN might also be a trigger i could use to run a script when the config (IP) would change.

OpenVPN is certainly able to allow a hook for a shell script when various important things happen, such as a session coming up or going down. This is managed within the OpenVPN configuration.
 
Joined
Mar 6, 2014
Messages
686
Thanks! These are great starters for more research
 
Joined
Mar 6, 2014
Messages
686
rc.conf doesn't kick off applications. It is technically a shell script but its role in life is to be a place to set variables for the rc subsystem.
Did a little reading on the rc subsystem. Found somthing interesting here.
If i find out which conditions the VPN startup script provides in rc.d (or add them myself), i could use those to require them in the firewall startup script in rc.d to make sure it is kicked. The loop and sleep in my firewall rules script (the one above) will then take care to wait for the vpn tunnel to come up.

Am i on the right track here?
 

joeschmuck

Old Man
Moderator
Joined
May 28, 2011
Messages
10,970
Yea, my wording was incorrect describing rc.conf kicks off the software, I do actually understand it doesn't. Sorry for misleading you.

Your link, I've been there quite a lot a few years back when we were releasing FreeNAS 8.02 and boy did I learn a lot the hard way.

I think you are on the right track, find out what OpenVPN can provide you in order to trigger the firewall rules script. You won't even need to have the firewall script in the rc.conf file which is actually nice. It would be ideal if OpenVPN set out an event each time the IP address changes or is valid/not valid. I have no idea what OpenVPN can do but good luck!
 

jgreco

Resident Grinch
Joined
May 29, 2011
Messages
18,681
Did a little reading on the rc subsystem. Found somthing interesting here.
If i find out which conditions the VPN startup script provides in rc.d (or add them myself), i could use those to require them in the firewall startup script in rc.d to make sure it is kicked. The loop and sleep in my firewall rules script (the one above) will then take care to wait for the vpn tunnel to come up.

Am i on the right track here?

I don't think you're on a good track, no. Part of the problem is that the rc system is part of the base system and therefore changes made to it are not persistent across upgrades/updates. However, another aspect is that the rc system would not guarantee that OpenVPN is actually up and had actually plumbed the interfaces at the point that the next dependent rc script boots; it merely guarantees that it has been kicked off.

What you're actually best pursuing is one of the OpenVPN script hooks, such as "up" or "down". A Linux-oriented discussion of that is http://askubuntu.com/questions/28733/how-do-i-run-a-script-after-openvpn-has-connected-successfully but is largely relevant on FreeBSD. I can't really help you a ton more than that, because while we make extensive use of OpenVPN and scripts here, pretty much every other aspect here is different ... we don't run it on FreeNAS, we don't run tun devices, etc.
 
Joined
Mar 6, 2014
Messages
686
Not to question your knowledge at all jgreco, but i do have some concerns/questions (or maybe i just don't understand correctly):
I don't think you're on a good track, no. Part of the problem is that the rc system is part of the base system and therefore changes made to it are not persistent across upgrades/updates.
I don't understand. The OpenVPN installation survives an upgrade/update, so if i change something on the OpenVPN startup script, why wouldn't this survive?

However, another aspect is that the rc system would not guarantee that OpenVPN is actually up and had actually plumbed the interfaces at the point that the next dependent rc script boots; it merely guarantees that it has been kicked off.
If i can kick the OpenVPN service before the firewall is kicked, the firewall rules script takes care of waiting until the tunnel is actually up.

I think you are on the right track, find out what OpenVPN can provide you in order to trigger the firewall rules script. You won't even need to have the firewall script in the rc.conf file which is actually nice. It would be ideal if OpenVPN set out an event each time the IP address changes or is valid/not valid. I have no idea what OpenVPN can do but good luck!
What you're actually best pursuing is one of the OpenVPN script hooks, such as "up" or "down". A Linux-oriented discussion of that is http://askubuntu.com/questions/28733/how-do-i-run-a-script-after-openvpn-has-connected-successfully but is largely relevant on FreeBSD. I can't really help you a ton more than that, because while we make extensive use of OpenVPN and scripts here, pretty much every other aspect here is different ... we don't run it on FreeNAS, we don't run tun devices, etc.
Wow, that's really helpful! Seems like the best solution here actually. Only problem is, that when the VPN connection does'nt come up, the firewall doesn't start. Alhough, i could start the firewall blocking all but the VPN service IP (which is fixed) and have a script change the rules after OpenVPN starts. I can now even let OpenVPN run a script if the IP changes, like you guys suggested earlier (which i thought would still maybe a bit too difficult for me to handle) :)
 

jgreco

Resident Grinch
Joined
May 29, 2011
Messages
18,681
Not to question your knowledge at all jgreco, but i do have some concerns/questions (or maybe i just don't understand correctly):
I don't understand. The OpenVPN installation survives an upgrade/update, so if i change something on the OpenVPN startup script, why wouldn't this survive?

I have no idea how OpenVPN is implemented on FreeNAS. However, I do know that the architecture of the system is such that the base system is treated as a firmware image. If OpenVPN has been stuck inside a jail or something similar, that would survive firmware updates, but then introduces other complications, such as that I don't believe ipfw is supported from within jails, which means you'd need to ssh to the host system. Basically I know less about OpenVPN on FreeNAS than you do. Take that for whatever it is worth.

If i can kick the OpenVPN service before the firewall is kicked, the firewall rules script takes care of waiting until the tunnel is actually up.


Wow, that's really helpful! Seems like the best solution here actually. Only problem is, that when the VPN connection does'nt come up, the firewall doesn't start. Alhough, i could start the firewall blocking all but the VPN service IP (which is fixed) and have a script change the rules after OpenVPN starts. I can now even let OpenVPN run a script if the IP changes, like you guys suggested earlier (which i thought would still maybe a bit too difficult for me to handle) :)

Bearing in mind that we very much frown upon placing a FreeNAS in any environment where it is visible to a situation where a firewall is required, I will note that you can set up a hook in FreeNAS to call a script upon system startup. It's somewhere under the system menu, I believe. You can put general stuff in there and then have a set of up/down scripts for OpenVPN that add/subtract specific functionality. Do not forget the down script; you do not want a hundred sequential OpenVPN sessions adding a hundred firewall rules ;-)
 
Status
Not open for further replies.
Top