What's new

OpenVPN Server with LAN Only?

  • SNBForums Code of Conduct

    SNBForums is a community for everyone, no matter what their level of experience.

    Please be tolerant and patient of others, especially newcomers. We are all here to share and learn!

    The rules are simple: Be patient, be nice, be helpful or be gone!

@ColinTaylor. Thanks Colin. What's NSF? I put "NSF generated iptables" into Google and it insists I mean NFS, not that those results look promising.

And many thanks for the info on tags. I did wonder if just typing @ followed by your handle might work and dismissed it as absurdly simple without even giving it a go. I even tried a couple of those icons in the editing menu!
 
@martinr Just a quick update to say that I tested out our theory (as much as I'm able) and it does indeed appear to work.:)

iptables -I FORWARD -s 10.8.0.0/24 -o eth0 -j DROP

Perhaps to make it more compatible with routers that don't use eth0 as their WAN interface the following might be better:

iptables -I FORWARD -s 10.8.0.0/24 -o $(nvram get wan0_ifname) -j DROP

Or even this! :D

iptables -I FORWARD -s $(nvram get vpn_client1_local)/$(nvram get vpn_client1_nm) -o $(nvram get wan0_ifname) -j DROP

Edit: correction

iptables -I FORWARD -s $(nvram get vpn_server1_local)/$(nvram get vpn_server1_nm) -o $(nvram get wan0_ifname) -j DROP
 
Last edited:
@ColinTaylor So I was right, after all: "Colin's a regular, Part-of-the-Furniture contributor who's very knowledgable on firewall rules."

Thanks, Colin; you've spurred me on to try and get better acquainted with iptables.
 
Or even this! :D

iptables -I FORWARD -s $(nvram get vpn_client1_local)/$(nvram get vpn_client1_nm) -o $(nvram get wan0_ifname) -j DROP

Whilst technically correct, use of the NVRAM vpn_client* variables implements old-skool WAN blocking for the router's 5 VPN Clients outbound via tun1X

In the OP
Is there anyway to make the OpenVPN server give LAN only access to clients (in this case Android phone)? ie. No internet access, just access to locally connected devices/servers.

the Android phone when it connects inbound via tun2X, will be assigned an I/P address from the VPN Server pool defined in the GUI

e.g. VPN Server 2

upload_2017-8-22_8-28-37.png


and will never create a NVRAM variable.

Or have I misunderstood the original question?:confused:
 
Whilst technically correct, use of the NVRAM vpn_client* variables implements old-skool WAN blocking for the router's 5 VPN Clients outbound via tun1X
Doh! :oops: Well spotted.

@Martineau You are correct. In my haste I mistakenly used the client NVRAM variables instead of the server ones. So I should have said:

iptables -I FORWARD -s $(nvram get vpn_server1_local)/$(nvram get vpn_server1_nm) -o $(nvram get wan0_ifname) -j DROP

Of course this is now just for academic amusement and if we wanted to do this properly we'd have to work it in into a proper script. :)

I'm not sure what you mean by this though:
the Android phone when it connects inbound via tun2X, will be assigned an I/P address from the VPN Server pool defined in the GUI... and will never create a NVRAM variable.
Are you thinking he wanted to block a single client? My understanding was that he wanted to block all clients connecting to that VPN server:
Code:
# nvram show | grep vpn_server | grep _remote | sort
vpn_server1_remote=10.8.0.2
vpn_server2_remote=10.16.0.2
vpn_server_remote=10.8.0.2
# nvram show | grep vpn_server | grep _nm | sort
vpn_server1_nm=255.255.255.0
vpn_server2_nm=255.255.255.0
vpn_server_nm=255.255.255.0
 
I'm not sure what you mean by this though:

Martineau said:

the Android phone when it connects inbound via tun2X, will be assigned an I/P address from the VPN Server pool defined in the GUI... and will never create a NVRAM variable.

Are you thinking he wanted to block a single client? My understanding was that he wanted to block all clients connecting to that VPN server:

Since the OP explicitly stated "Android phone" I assumed this was the case e.g. he may be sharing say legitimate streaming media content hosted on his LAN to friends, but for these selected users he wishes to ensure that they don't 'accidentally' configure their Android phone's OpenVPN Client to 'Redirect ALL traffic via VPN=YES' and (ab)use his ISP WAN connection for potentially 'dubious' content.

However he may wish to ensure that from his phone he can continue to access any Internet content via his 'private' WAN, so a block on all clients would be inappropriate - hence the 'single device WAN block' scenario consideration/solution.

NOTE: I use this technique in my custom OpenVPN 'client-connect' script which has access to the current OpenVPN environment variables etc.
Code:
<snip>
case "$LINE" in
   ifconfig-push* | staticip* )
          Parse "$LINE" " " KEYWORD IP_ADDR SUBNET_MASK
          # Let's give the lazy/numpty user a helping hand!
          # e.g. 'staticip 88' -> 'ifconfig-push ${POOL_SUBNET}.88 255.255.255.0'
          #
          #logger -st "($(basename $0))" $$ "***DEBUG KEYWORD="$KEYWORD
          case "$KEYWORD" in
                ifconfig-push | staticip)       # IPv4......
                if [ "$KEYWORD" == "staticip" ];then   # My psuedo OpenVPN server directive
                    KEYWORD="ifconfig-push"      # Use real OpenVPN IPv4 statement rather than our 'staticip' codeword
                  logger -st "($(basename $0))" $$ "Psuedo command 'staticip' converted to 'ifconfig-push'!"
                 fi
                 if [ -z "$SUBNET_MASK" ];then
                     SUBNET_MASK="255.255.255.0"     # IPv4 ONLY! - Use the default subnet mask if ommitted!
                 fi
                if [ $(echo "$IP_ADDR" | grep -o "\." | wc -l) -eq 0 ];then   # Only a number specified ?
                    IP_ADDR=${POOL_SUBNET}.$IP_ADDR
                     echo -e $KEYWORD $IP_ADDR $SUBNET_MASK >> $CCD_FILE
                else
                   echo -e $KEYWORD $IP_ADDR $SUBNET_MASK >> $CCD_FILE    # Use full I/P address as supplied
               fi
                  ;;
                *ipv6* | *ip6*)         # IPv6
                        if [ "$KEYWORD" == "staticip6" ];then   # My psuedo OpenVPN server directive
                        KEYWORD="ifconfig-ipv6-push"    # Use real OpenVPN IPv6 statement rather than our 'staticip6' codeword
                       # e.g. ifconfig-ipv6-push 2a03:b0c0:1:d0::7f:8003/64  recommended to use /64
                       logger -st "($(basename $0))" $$ "Psuedo command 'staticip6' converted to 'ifconfig-ipv6-push'!"
                   fi
           echo -e $KEYWORD $IP_ADDR $SUBNET_MASK >> $CCD_FILE
           ;;
          esac
          ;;
   *passthru*)            # My pseudo OpenVPN server directive
          # This client will 'pass-thru' the router and use the VPN client specified
          # e.g. pass-thru 2
          Parse "$LINE" " " KEYWORD VPN_NUM
          PASSTHRU=1
          ;;
   *forcedns*)            # My pseudo OpenVPN server directive
          # This client cannot override the pushed DNS
          # e.g. forcedns 10.0.0.254
          Parse "$LINE" " " KEYWORD FORCED_DNS
          FORCEDNS=1
          ;;
   *lanonly*)            #  My pseudo OpenVPN server directive
          # This client cannot 'pass-thru' outbound via the WAN or any VPN Client tunnel; only LAN resources are accessible
          LANONLY=1
          ;;
   *)
          echo -e "$LINE" >> $CCD_FILE  # Assume user has RTFM'd ADVANCED CCD directive & specified correct syntax!!!
             # i.e. push,push-reset,iroute,iroute-ipv6,disable and config
          ;;
   esac

 # Was the 'pass-thru' directive found? and 'LAN only' wasn't specified
 if [ "$PASSTHRU" == "1" ] && [ "$LANONLY" != "1" ];then
   <snip>
 fi

 # Was the 'lanonly' directive found?
 if [ "$LANONLY" == "1" ];then
      logger -st "($(basename $0))" $$ "Psuedo command 'lanonly' will be applied to I/P" $IP_ADDR
      iptables -D FORWARD -i tun2${VPN_SERVER_ID} -s $IP_ADDR -o $(nvram get wan0_ifname) -m state --state NEW -j DROP
      iptables -I FORWARD -i tun2${VPN_SERVER_ID} -s $IP_ADDR -o $(nvram get wan0_ifname) -m state --state NEW -j DROP
 fi

<snip>
 
Last edited:
When I clarified his aim with him, he did say the following understanding was correct: "that when the remote clients are connected to your OpenVPN server, those remote clients must not be able to connect to the Internet by any means, neither through the VPN nor through the remote network they are on."

Nevertheless, this topic is getting really interesting,.....
 
Hi @Martineau You may be right about the number of client devices involved, it's not clear.

Also thanks for the code example which confirms what @martinr and I were discussing, i.e. whether it was even possible to block the internet traffic. It's reassuring to discover that we came to essentially the same solution as you had already created :rolleyes:. But yours is much more elegant and versatile. :)

Anything beyond this is out of my league I'm afraid. As I said before, I don't use OpenVPN myself so am not familiar with its intricacies.
 
He seems to be dynamically updating his script as he posts it. ;) Certainly it doesn't look like this anymore.

The 'VPNClient-connect.sh' script v3.01 (as posted back in March) was posted to explicitly address a specific question:

i.e. "How to assign a static I/P to a connecting OpenVPN client"

Unsurprisingly, my 'VPNClient-connect.sh' script has evolved over the last 4 months (currently v4.51) and I don't feel any obligation to update that specific post with a more feature laden script that now (as it contains 150% more code) would potentially be over-kill and possibly confusing to users looking for a concise solution to the original query.

Surely it is my prerogative to decide which scripts I post to the forum?, and personally find your post rather spiteful.
 
Last edited:
.

Surely it is my prerogative to decide which scripts I post to the forum?, and personally find your post rather spiteful.

Honestly, @Martineau , I think you've misunderstood Colin's remarks. I'm totally convinced nothing could be more removed from the truth. I read Colin's post as: "this is a work in progress from somone very knowledgable in scripts and firewall rules. "

Really, I think you're 180 degrees out of phase on Colin's comments.
 
I apologise for causing offence @Martineau , that was not my intention at all. It was just my feeble attempt at humour based on the fact that when I re-read the code fragment you posted it had changed from what was there a few minutes earlier.

I always have the highest respect for your knowledge and all the help you have given to the members of this forum.

Surely it is my prerogative to decide which scripts I post to the forum?, and personally find your post rather spiteful.
Again, I apologise for my misunderstanding. I definitely don't expect you to go back and update old posts, or be under any obligation as to what you post. I thought the code fragment you posted was referring to something that was already on the forum, but the post I linked to was the most recent I could find.
 
I apologise for causing offence @Martineau
Apology accepted.
when I re-read the code fragment you posted it had changed from what was there a few minutes earlier.
I am indeed guilty of revising my forum posts (sometimes several updates in the space of a few mins) until I am satisfied; especially with the layout.

In particular I do find it extremely frustrating when I carefully copy'n'paste inside the code tags, and the annoying random loss of tidy/human-friendly indentation of complex if;else;fi and case;esac etc. clauses inevitably triggers OCD.

Manually correcting lengthy scripts gets tedious very quickly, so sometimes I choose to simply post short relevant non-contiguous fragments from the full script to illustrate my solution.

Sadly, posting code fragments also has its downside as it is all too easy to omit a crucial piece of code that makes understanding/following the posted code impossible for others, resulting in even more hurried EDIT tweaks.

Regards,
 
Gist is great for that kind of thing, just like a regular Git you can easily view past history.
 
Wow looks like the discussion has kept going after I had found a solution. Well what I thought was a solution was really just a half solution so I'm kind of back to square one. Giving a dud DNS inside the client (Android phone running OpenVPN for Android) does somewhat kill internet but there are some apps that spend some time trying to get internet before realizing it can't and only then does it go into offline mine. Or it just hangs. Take the Google voice app for example:

It does have offline voice support. So if you put the phone on Airplane mode or use an app like NoRootFirewall to block internet access, it knows right away there's no internet and goes into offline mode and offline dictation works right away. But with my workaround of connecting to the Asus VPN back home but giving it a dud DNS on the client (192.0.0.0) just makes the app hang after receiving voice input instead of going into offline mode.

Don't know if that made sense, but I'm kind of back to square 1. I'm really not sure if the solution to the problem even exists now. I do essentially still want a VPN connection back to my home network that allows my phone to access locally running servers at home but not have any internet access at all.
 
Gist is great for that kind of thing, just like a regular Git you can easily view past history.
I have benefited from the knowledge and scripts written by @Martineau. I always learn something new. I hope that in the future he will consider posting and consolidating them on gist or similar site. I would even make a paypal donation.
 

Similar threads

Support SNBForums w/ Amazon

If you'd like to support SNBForums, just use this link and buy anything on Amazon. Thanks!

Sign Up For SNBForums Daily Digest

Get an update of what's new every day delivered to your mailbox. Sign up here!
Top