How to test if a gateway is online from a bash script? (Script Included)
-
Can someone please tell me how I can test if a VPN gateway is online and has connectivity from a bash script?
I tried:
[2.4.4-RELEASE][root@pfsense]/root: ping -c 3 -I ovpnc1 8.8.8.8 ping: invalid multicast interface: `ovpnc1'
which didn't work, so just as a test I also tried to ping on the main WAN gateway interface:
[2.4.4-RELEASE][root@pfsense]/root: ping -c 3 -I em0 8.8.8.8 ping: invalid multicast interface: `em0'
and that didn't work either. (see relevent ifconfig output for those interfaces)
What I'm missing? (My plan is to test $? from the ping command.)
[2.4.4-RELEASE][root@pfsense]/root: ifconfig em0: flags=8943<UP,BROADCAST,RUNNING,PROMISC,SIMPLEX,MULTICAST> metric 0 mtu 1500 options=219b<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,VLAN_HWCSUM,TSO4,WOL_MAGIC> ether 00:28:1a:e0:10:04 hwaddr 00:28:1a:e0:10:04 inet6 fe80::228:1aff:fee0:1004%em0 prefixlen 64 scopeid 0x1 inet 99.254.36.133 netmask 0xfffffe00 broadcast 255.255.255.255 nd6 options=21<PERFORMNUD,AUTO_LINKLOCAL> media: Ethernet autoselect (1000baseT <full-duplex>) status: active ovpnc1: flags=8051<UP,POINTOPOINT,RUNNING,MULTICAST> metric 0 mtu 1500 options=80000<LINKSTATE> inet6 fe80::228:1aff:fee0:1004%ovpnc1 prefixlen 64 scopeid 0x28 inet 10.62.10.6 --> 10.62.10.5 netmask 0xffffffff nd6 options=21<PERFORMNUD,AUTO_LINKLOCAL> groups: tun openvpn Opened by PID 96995
-
parse this
root@pfsense.lan]/root: pfSsh.php playback gatewaystatus
-
Thanks @heper -- I guess that could work. BTW, are these calls documented somewhere?
Is there any way I can directly communicate through the VPN interface?
@heper said in How to test if a gateway is online from a bash script?:
parse this
root@pfsense.lan]/root: pfSsh.php playback gatewaystatus
-
From the FreeBSD manpage:
-I interface Source multicast packets with the given interface address. This flag only applies if the ping destination is a multicast address.
Try -S instead with your Interface address.
-Rico
-
@Rico said in How to test if a gateway is online from a bash script?:
From the FreeBSD manpage:
-I interface Source multicast packets with the given interface address. This flag only applies if the ping destination is a multicast address.
Try -S instead with your Interface address.
-Rico
Thanks @Rico that worked.... only problem is that it turns out that ICMP is firewalled off on the VPN.
So I tred to do something with curl, and I'm wondering why this doesn't work:
ovpnc1: flags=8051<UP,POINTOPOINT,RUNNING,MULTICAST> metric 0 mtu 1500 options=80000<LINKSTATE> inet6 fe80::228:1aff:fee0:1004%ovpnc1 prefixlen 64 scopeid 0x28 inet 10.62.10.6 --> 10.62.10.5 netmask 0xffffffff nd6 options=21<PERFORMNUD,AUTO_LINKLOCAL> groups: tun openvpn Opened by PID 96995 curl -v -4 --interface 10.62.10.6 http://google.com * Expire in 0 ms for 6 (transfer 0x803a94000) * Expire in 1 ms for 1 (transfer 0x803a94000) [Similar lines removed] * Expire in 0 ms for 1 (transfer 0x803a94000) * Expire in 0 ms for 1 (transfer 0x803a94000) * Trying 172.217.1.174... * TCP_NODELAY set * Name '10.62.10.6' family 2 resolved to '10.62.10.6' family 2 * Local port: 0 * Expire in 200 ms for 4 (transfer 0x803a94000) * connect to 172.217.1.174 port 80 failed: Operation timed out * Failed to connect to google.com port 80: Operation timed out * Closing connection 0 curl: (7) Failed to connect to google.com port 80: Operation timed out curl -v -4 --interface 10.62.10.5 http://google.com * Expire in 0 ms for 6 (transfer 0x803a94000) * Expire in 1 ms for 1 (transfer 0x803a94000) [Similar lines removed] * Expire in 50 ms for 1 (transfer 0x803a94000) * Trying 172.217.1.174... * TCP_NODELAY set * Name '10.62.10.5' family 2 resolved to '10.62.10.5' family 2 * bind failed with errno 49: Can't assign requested address * Closing connection 0 curl: (45) bind failed with errno 49: Can't assign requested address
The curl statement does work when I don't specify an interface:
curl -v -4 http://google.com * Expire in 0 ms for 6 (transfer 0x803a94000) * Expire in 1 ms for 1 (transfer 0x803a94000) [Similar lines removed] * Expire in 200 ms for 1 (transfer 0x803a94000) * Expire in 200 ms for 1 (transfer 0x803a94000) * Trying 172.217.1.174... * TCP_NODELAY set * Expire in 200 ms for 4 (transfer 0x803a94000) * Connected to google.com (172.217.1.174) port 80 (#0) > GET / HTTP/1.1 > Host: google.com > User-Agent: curl/7.64.0 > Accept: */* > < HTTP/1.1 301 Moved Permanently < Location: http://www.google.com/ < Content-Type: text/html; charset=UTF-8 < Date: Fri, 06 Mar 2020 07:39:36 GMT < Expires: Sun, 05 Apr 2020 07:39:36 GMT < Cache-Control: public, max-age=2592000 < Server: gws < Content-Length: 219 < X-XSS-Protection: 0 < X-Frame-Options: SAMEORIGIN < <HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8"> <TITLE>301 Moved</TITLE></HEAD><BODY> <H1>301 Moved</H1> The document has moved <A HREF="http://www.google.com/">here</A>. </BODY></HTML> * Connection #0 to host google.com left intact [2.4.4-RELEASE][root@guardian.pvt]/root:
Alternatively is there any other way I might route out the OpenVPN interface to test connectivity to a site that is very unlikely to be down, and hence a reliable way to determine if the interface is working.
-
Here's a script I wrote a few years ago. It's for bash on LInux, but it should work with FreeBSD.
#! /bin/sh
while [ 1 ]
do
ping <destination> -4 -c 1 || date >> ~/log;sleep 50
doneReplace <destination> with the gateway address and you will have a log file of when it failed. You can adjust the sleep time to taste.
-
@JKnott said in How to test if a gateway is online from a bash script?:
Here's a script I wrote a few years ago. It's for bash on LInux, but it should work with FreeBSD.
#! /bin/sh
while [ 1 ]
do
ping <destination> -4 -c 1 || date >> ~/log;sleep 50
doneReplace <destination> with the gateway address and you will have a log file of when it failed. You can adjust the sleep time to taste.
@JKnott unfortunately that won't work... a couple of problmes
- FreeBSD doesn't have a -4 option (I wish FreeBSD would get their utilities on par with GNU linux)
- The ping doesn't route through the OpenVPN interface. AFAICR connectivity can go down but the interface address doesn't disappear
- ping -S does work, but on testing it, I found out that the VPN Tunnel firewall blocks ICMP, so I can't use ping at all.
Since ping is blocked, I need to use something like curl (not attached to curl) that uses a common protocol to a site like google.
I tried
curl --interface ovpnc1 http://ifconfig.me and curl --interface 10.62.10.6 http://ifconfig.me
and neither of them worked - the connection timed out., but once I removed --interface the command:
curl http://ifconfig.me
correctly returns the IP address of the main WAN interface. How can I make curl use the VPN?
Alternatively this dig command looks interesting as well, but I can't route it through the VPN.
dig TXT +short o-o.myaddr.l.google.com @ns1.google.com
Th above command correctly returns the main WAN IP address, but this command:
dig -b10.62.10.5 TXT +short o-o.myaddr.l.google.com @ns1.google.com dig: isc_socket_bind: address not available
fails as shown.
Any suggestions would be much appreciated.
-
@guardian said in How to test if a gateway is online from a bash script?:
FreeBSD doesn't have a -4 option
All that does is force IPv4, when a host name returns both IPv4 and IPv6 addresses. If you specify an actual IPv4 address, rather than host name, IPv4 will be used. You used. 8.8.8.8, so the -4 option is irrelevant.
-
@guardian said in How to test if a gateway is online from a bash script?:
I wish FreeBSD would get their utilities on par with GNU linux
There is zero reason for
ping -4
on FreeBSD since there isping
andping6
-
@Derelict said in How to test if a gateway is online from a bash script?:
There is zero reason for ping -4 on FreeBSD since there is ping and ping6
Linux used to work that way. Now, ping works with both IPv4 and IPv6. If both addresses are returned for a host name, it prefers IPv6. However, there is still a ping6 command, which is linked to ping.
-
This is for
tcsh
but I understand that should be very similar and easy to apply tobash
#!/bin/tcsh set gw = `/usr/local/bin/php /usr/local/sbin/pfSsh.php playback gatewaystatus | grep WAN ` set gwping = `echo $gw | awk '{ ORS=" "; print $6 }' ` set gwstatus = `echo $gw | awk '{ ORS=" "; print $7 }' `
-
@Derelict said in How to test if a gateway is online from a bash script?:
@guardian said in How to test if a gateway is online from a bash script?:
I wish FreeBSD would get their utilities on par with GNU linux
There is zero reason for
ping -4
on FreeBSD since there isping
andping6
@JKnott said in How to test if a gateway is online from a bash script?:
@Derelict said in How to test if a gateway is online from a bash script?:
There is zero reason for ping -4 on FreeBSD since there is ping and ping6
Linux used to work that way. Now, ping works with both IPv4 and IPv6. If both addresses are returned for a host name, it prefers IPv6. However, there is still a ping6 command, which is linked to ping.
@JKnott @Derelict Thanks very much for this - I'm struggling with FreeBSD, after 2 years, I'm just beginning to get comfotable with Linux
@hectorspc said in How to test if a gateway is online from a bash script?:
This is for
tcsh
but I understand that should be very similar and easy to apply tobash
#!/bin/tcsh set gw = `/usr/local/bin/php /usr/local/sbin/pfSsh.php playback gatewaystatus | grep WAN ` set gwping = `echo $gw | awk '{ ORS=" "; print $6 }' ` set gwstatus = `echo $gw | awk '{ ORS=" "; print $7 }' `
@hectorspc - I decided to just use the gateway status.
For the benefit of anyone who may wish to do something similar, here's the script I came up with;
(Code review's welcome - goal was clarity/ease if maintenace/self-documenting not conciseness)#!/bin/sh # # restartvpn: Restart the OpenVPN client if it is down. The restart is supressed # if the WAN is down. # # -f / -F : Force: Force reset even if VPN is not down # -q / -Q : Quiet: Supress printed output # WAN_ID='WAN_DHCP' # WAN Gateway ID String VPN_IDs='VPN_UDP_TOS_VPNV4' # VPN Gateway ID Strings (Separate with a space) VPN_GWs='1' # VPN Client ID of gateway GW_DOWN='down' # Gateway down status string # -q / -Q : Quiet: Supress printed output silent=$(echo $@- | awk '{print (/-[qQ]/ ? 1 : 0)}') # -f / -F : Force: Force reset even if VPN is not down force=$(echo $@ | awk '{print (/-[fF]/ ? 1 : 0)}') restartvpn(){ # # Restart VPN client $VPN_GW # WD=$([ "$WAN_STAT" = "$GW_DOWN" ] && echo "WAN DOWN:" || echo "") FC=$([ $force -eq 1 ] && echo "FORCED:" || echo "") echo $(date +%y/%m/%d-%H:%M:%S-)${ID}-${WD}${FC}$(/usr/local/sbin/pfSsh.php playback svc restart openvpn client $VPN_GW) } gwstat=$(pfSsh.php playback gatewaystatus) WAN_STAT=$(echo "$gwstat" | awk '/'$WAN_ID'/{print $NF}') PUBLIC_IP=$(echo "$gwstat" | awk '/'$WAN_ID'/{print $3}') if [ $silent -eq 0 ];then echo -e "$(basename $0) - Public IP: $PUBLIC_IP - $(date)\n\n$gwstat\n" fi if [ "$WAN_STAT" = "$GW_DOWN" -a $force -eq 0 ];then echo "$(date +%y/%m/%d-%H:%M:%S-)WAN is down-VPN restart not attempted." return 1 fi gw=1 for ID in $VPN_IDs;do VPN_STAT=$(echo "$gwstat" | awk '/'$ID'/{print $NF}') VPN_GW=$(echo $VPN_GWs|cut -w -f $gw) if [ -n "$VPN_STAT" ];then [ $silent -eq 0 ] && echo VPN Gateway: $ID - $([ "$VPN_STAT" = "$GW_DOWN" ] && echo "DOWN" || echo "UP") if [ "$VPN_STAT" = "$GW_DOWN" -o $force -eq 1 ];then restartvpn return 1 fi else [ $silent -eq 0 ] && echo No active gateway $ID fi gw=gw+1 done
When run from the command line the output looks like this:
# restartvpn restartvpn - Public IP: 99.254.36.133 - Sun Mar 8 17:15:45 EDT 2020 Name Monitor Source Delay StdDev Loss Status VPN_UDP_TOS_VPNV4 8.8.4.4 10.12.11.6 29.443ms 10.624ms 27% down WAN_DHCP 8.8.8.8 99.254.36.133 11.329ms 6.142ms 0.0% none VPN Gateway: VPN_UDP_TOS_VPNV4 - DOWN 20/03/08-17:15:45-VPN_UDP_TOS_VPNV4-Attempting to issue restart to openvpn service... openvpn has been restarted.
I have set it up to run as a cron job:
*/3 * * * * root /root/bin/restartvpn -q
Hopefully someone will find this helpful.
-
Many thanks to all who provided assistance. Here is the finished script for anyone who may want to use/adapt it. If anyone wants to review/ provide suggestions or sees that I've done anything that could cause issues, please feel free to do so.
#!/bin/sh # # restartvpn: Restart the OpenVPN client if it is down. The restart is supressed # if the WAN is down. # # -f / -F : Force: Force reset even if VPN is not down # -q / -Q : Quiet: Supress printed output # WAN_ID='WAN_DHCP' # WAN Gateway ID String VPN_IDs='XXXXX_VPNV4' # VPN Gateway ID Strings (Separate with a space) VPN_GWs='1' # VPN Client ID of gateway GW_DOWN='down' # Gateway down status string # -q / -Q : Quiet: Supress printed output silent=$(echo $@- | awk '{print (/-[qQ]/ ? 1 : 0)}') # -f / -F : Force: Force reset even if VPN is not down force=$(echo $@ | awk '{print (/-[fF]/ ? 1 : 0)}') restartvpn(){ # # Restart VPN client $VPN_GW # WD=$([ "$WAN_STAT" = "$GW_DOWN" ] && echo "WAN DOWN:" || echo "") FC=$([ $force -eq 1 ] && echo "FORCED:" || echo "") msg=$(echo $(date +%y/%m/%d-%H:%M:%S-)${ID}-${WD}${FC}$(/usr/local/sbin/pfSsh.php playback svc restart openvpn client $VPN_GW)) [ $silent -eq 0 ] && echo $msg logger "***** ${msg}" } gwstat=$(pfSsh.php playback gatewaystatus) WAN_STAT=$(echo "$gwstat" | awk '/'$WAN_ID'/{print $NF}') PUBLIC_IP=$(echo "$gwstat" | awk '/'$WAN_ID'/{print $3}') if [ $silent -eq 0 ];then echo -e "$(basename $0) - Public IP: $PUBLIC_IP - $(date)\n\n$gwstat\n" fi if [ "$WAN_STAT" = "$GW_DOWN" -a $force -eq 0 ];then msg=$(echo "$(date +%y/%m/%d-%H:%M:%S-)WAN is down-VPN restart not attempted.") [ $silent -eq 0 ] && echo $msg logger "***** ${msg}" return 1 fi gw=1 for ID in $VPN_IDs;do VPN_STAT=$(echo "$gwstat" | awk '/'$ID'/{print $NF}') VPN_GW=$(echo $VPN_GWs|cut -w -f $gw) if [ -n "$VPN_STAT" ];then [ $silent -eq 0 ] && echo VPN Gateway: $ID - $([ "$VPN_STAT" = "$GW_DOWN" ] && echo "DOWN" || echo "UP") if [ "$VPN_STAT" = "$GW_DOWN" -o $force -eq 1 ];then restartvpn return 1 fi else [ $silent -eq 0 ] && echo No active gateway $ID fi gw=gw+1 done