How can I forward a port to another computer but maintain the originating IP?

Discussion in 'Tomato Firmware' started by ras07, Apr 22, 2019.

  1. ras07

    ras07 Network Guru Member

    I need to forward traffic coming into a cloud-provisioned Ubuntu VPS at 1.1.1.100 on port 1234 to port 5678 on local Windows computer (192.168.0.200, which is behind a Tomato router at 2.2.2.200 / 192.168.0.1), but to preserve the originating IP address. The router forwards port 5678 to the Windows machine.

    When I run this on the VPS:
    iptables -t nat -A PREROUTING -p tcp --dport 1234 -j DNAT --to-destination 2.2.2.200:5678
    iptables -t nat -A POSTROUTING -p tcp -d 2.2.2.200 --dport 5678 -j SNAT --to-source 1.1.1.100​

    then the packets get forwarded but the Windows server at 2.2.2.200 192.168.0.200 thinks everything is coming from 1.1.1.100. The originating IP is lost.

    Is there a way to leave out the POSTROUTING SNAT command and tell the Tomato router to route all relevant traffic back from 2.2.2.200 192.168.0.200 back through 1.1.1.100?
     
    Last edited: Apr 22, 2019
  2. eibgrad

    eibgrad Network Guru Member

    The only time you would need to SNAT a port forward w/ tomato is if the replies would otherwise not automatically be returned to that same gateway. And most of the time, the target *is* using that tomato router as its default gateway, so the SNAT is unnecessary.
     
  3. ras07

    ras07 Network Guru Member

    In this case it's the remote computer doing the NATting, though - so it's not using the same gateway. I need to somehow route traffic back from the local Windows box to the remote VPS, without SNATting the traffic.
     
  4. eibgrad

    eibgrad Network Guru Member

    Then you have to add a static route to the Windows machine that tells it to route traffic from that particular client's IP back through that gateway, rather than its normal default gateway.
     
  5. eibgrad

    eibgrad Network Guru Member

    Btw, I don't know why you just can't stop SNAT'ing the traffic from the VPS entirely. If the traffic from the VPS is forward to the WAN of the tomato router (you said "server" at 2.2.2.200, but as I see it, that's the tomato router), then the tomato router *will* forward the client's IP to the target of that port forward. IOW, I don't see why you need the SNAT from the VPS to the tomato router in the first place. Not unless the tomato router itself is using some other gateway than that of the VPS.
     
  6. ras07

    ras07 Network Guru Member

    Yeah, I'm confusing myself (which is half the problem). I edited the original post to correct myself.

    If I leave the SNAT out entirely, it doesn't work (I think because the router tries to send the response directly back to the user's machine, which is expecting to hear from 1.1.1.100, not 2.2.2.200, so it discards the traffic.)

    What I think I need is to add a route command to the Tomato router that sends traffic from 192.168.0.200 back to 1.1.1.100. I haven't quite gotten that right, though.

    Here's a picture to keep things straight in my head:
    upload_2019-4-22_10-42-26.png
     
  7. eibgrad

    eibgrad Network Guru Member

    Yeah, that diagram makes a big difference. It was hard to get the big picture without it.

    So rather than the client accessing the tomato router directly, it's being directed to the VPS first, then to the tomato router. And I can see the problem. In order to force the replies back to the VPS, you need to SNAT it on the VPS. But that hides the public IP of the client.

    Obviously one solution is have the client access the tomato router directly, but I assume there's a reason to this madness. LOL

    I'm afraid you're stuck between a rock and hard place w/ this one. You have several conflicts here. If you disable SNAT on the VPS (which is the first requirement if the public IP is going to make it to the Windows server behind the tomato router), you have the problem of the tomato router than attempting to reply directly back to the client rather than via the VPS (acting as the first gateway). The client will obviously reject this; it will be seen as spoofed packets. What you would need is the ability to change the destination IP on the reply packets to that of the VPS server/gateway (i.e., DNAT). But DNAT is not allowed on the POSTROUTING chain of the nat table! DNAT is strictly for PREROUTING purposes.

    What I recommend is that you change the architecture. Establish an OpenVPN client (w/ NAT disabled) from the Linux server to the tomato router's OpenVPN server. That creates a second gateway on the tomato router which is directly bound to the VPS. Now you can add a static route to tomato that tells it to route traffic for the client (4.5.6.7) to the OpenVPN server's tunnel rather than the WAN.

    Code:
    # OpenVPN server config, under Custom Config
    route 4.5.6.7 255.255.255.255 vpn_gateway
    All this additional plumbing preserves the client's public IP across the various gateways. The one caveat though is that it will be difficult to generalize this for any given client's public IP that use the VPS as its initial gateway. IOW, a roaming client. For each client's public IP, you'll need to add a static route. Not unless those clients are all using some known subnet of the public IP space (4.5.0.0/16).

    One other thing regarding OpenVPN. It *might* be a bit simpler and more efficient to use an OpenVPN PTP tunnel in this case.

    https://openvpn.net/community-resources/static-key-mini-howto/

    But you can't do that via tomato's OpenVPN client or server GUIs. The GUIs will only work in a multi-client to server mode, requiring tls, certs, keys, etc. A PTP tunnel is much simpler and eliminates most of these things. But you'll have to configure it on both sides using scripts. If it helps, I happen to have such scripts from some testing I was doing between an OpenVPN client on the router, and and OpenVPN server running on my VPS. You would have to make a few changes to get it working for you. I wasn't sure you want to use up one of your OpenVPN server configs in the GUI just for this. Or maybe use the GUI first, get things working, and consider PTP later. Just something to think about.

    At least at the moment, that's how I see it. In a case like this, I tend to ponder the situation for a while, and sometimes come to a different conclusion. But just looking at this at the given moment, this seems to me to be the best approach. Yeah, a bit more of a hassle, but as I see it, you need to get the second gateway established on the tomato router so that you can force certain clients back to the VPN, and without the need for the SNAT. An OpenVPN tunnel would seem to be ideal.
     
    Last edited: Apr 22, 2019
  8. eibgrad

    eibgrad Network Guru Member

    P.S. One other detail I failed to mention. You obviously won't be routing the client over the WAN of the VPS anymore, but instead over the OpenVPN client. So the --to-destination of the PREROUTING rule on the VPS will change to the OpenVPN client (i.e., the tunnel), and you can eliminate the SNAT rule since the static route on the OpenVPN server side will handle the replies. All the while, the client's public IP remains intact.
     
  9. eibgrad

    eibgrad Network Guru Member

    P.S. I just thought of another way to handle the routing that would avoid static routes on a per client basis (as I said, for roaming clients, w/ ever changing public IPs, this would be problematic).

    If public access to that Windows server is *only* intended to be accessed via the VPS, then you could use PBR (policy based routing) on the tomato router to route any replies from that Windows server's LAN ip (192.168.0.200) over the VPN! IOW, this automates the process of routing, so it works for ALL clients coming from the VPN.

    I can show you how to do that, but before going into that level of detail, I want to know if your game for this solution.
     
  10. ras07

    ras07 Network Guru Member

    Thanks for the great explanation! I have a lot better understanding of the pitfalls now.

    What I didn't draw is that there are lots of clients that can roam, so the OpenVPN route isn't practical. But it's fine if the Windows server's only interface to the outside world is through the VPS at 1.1.1.100, so the PBR idea sounds workable. (Would be nice for other 192.168.0.x machines to be able to get to it w/o going through the VPS, but even that isn't a hard requirement.)

    I will read up on PBR in anticipation of your reply - Thanks!

    (I had another thought this afternoon which is probably a rabbit trail, so I will start a new reply for it)
     
  11. ras07

    ras07 Network Guru Member

    In thinking this over it occurred to me that the big problem is that the traffic is double-NATted - the Linux server at 1.1.1.100 NATs it once, and then the Tomato router at 2.2.2.200 NATs it again. If I established an OpenVPN virtual network (say, with 10.0.0.0/8 addressing) between the Linux server and the Windows server, I think I could then get away with only NATting once - the Linux server would NAT to the 10.x.x.x network, where the Windows server has an IP.

    Either the Linux box would have to be the OpenVPN server, or else the Tomato router could be the server and both the Linux and Windows boxes would be OpenVPN clients.

    Not sure I'm thrilled with this thought (the PBR idea sounds simpler) but I'm curious to know if it would work or if there's a flaw in my thinking.
     
  12. ras07

    ras07 Network Guru Member

    Another rabbit trail - I also tried SSH tunneling. I figured a remote tunnel from 1.1.1.100:1234 to 192.168.0.200:5678 (i.e., the equivalent of executing ssh -R 5678:localhost:1234 1.1.1.100 on the Windows machine) would do the trick (as long as the GatewayPorts option of sshd was enabled on the Linux box at 1.1.1.100). Again, this worked connectivity-wise, but it still made it look like all traffic came from 1.1.1.100. I've been trying to read up on SSH tunnels to understand exactly why this happens.
     
  13. eibgrad

    eibgrad Network Guru Member

    Don't get too far ahead of me. This is complicated, and if we start considering alternatives right now, we'll end up jumping back and forth between several solutions, and get all mixed up. Hear me out on the OpenVPN solution, then let's see whether it falls short, and if it does, then let's discuss some alternates, like SSH or whatever.

    So I've had a little more time to think through the details, and I think I've got a plan of action that will work. And it's not nearly as complicated as I thought it would be. And it's single NAT'd. Let's walk through it.

    Let's first assume the ultimate target is 192.168.0.200, and port 80. You were never precise about that, but just for clarity's sake, we'll make it port 80.

    1. You establish an OpenVPN client on the Linux server, and OpenVPN server on the tomato router. It needs to be a routed tunnel (tun), and let's specify the tunnel network as 10.8.0.0/24 (doesn't really matter, anything in the private IP space will do, as long as it doesn't conflict w/ either the local network of the VPS, or the local network behind the tomato router). You also need to add the following route directive to the OpenVPN client's config.

    Code:
    route 192.168.0.0 255.255.255.0 vpn_gateway
    Once the OpenVPN client is connected to the OpenVPN server, it will add that route to its local routing table. It tells the local routing table how to find that network, and that it lies on the other side of the VPN's tunnel.

    2. So some client on the public internet (let's say that's 4.5.6.7) wants to access the Windows server @ 192.168.0.200:80. That client references 1.1.1.100:1234 for these purposes. You need to have routing enabled on the Linux server, and the following NAT rule to DNAT that client from the public IP to the local IP of the Windows server.

    Code:
    iptables -t nat -A PREROUTING -p tcp --dport 1234 -j DNAT --to-destination 192.168.0.200:80
    Since the local routing table has been told to route the 192.168.0.0/24 network over the VPN, the traffic makes it way over to the OpenVPN server, where it's routed from the OpenVPN server's network interface (tun21) and into the LAN (br0). The Windows server @ 192.168.0.200 receives the traffic, and it sees the client's public IP (4.5.6.7).

    3. Now the Windows server replies, but when it sees a public IP, it only knows to route it back to the tomato router (2.2.2.200). And the tomato router's default gateway is the WAN, NOT the VPN. So we use PBR to force the replies back over the VPN.

    We need two scripts; one to build PBR, the other to tear it down. And we use the OpenVPN scripting engine to trigger those scripts.

    Code:
    cat << "EOF" > /jffs/route-up.sh
    #!/bin/sh
    ip route flush table 200 2> /dev/null
    ip route add default via $route_vpn_gateway table 200
    ip route flush cache
    ip rule add from 192.168.0.200 table 200
    EOF
    chmod +x /jffs/route-up.sh
    Open a shell (telnet/ssh) using Putty to the tomato router, and copy/paste this script into the terminal window. It will automatically create, install, and configure the permissions of the script. Do the same for the following script.

    Code:
    cat << "EOF" > /jffs/route-down.sh
    #!/bin/sh
    ip route flush table 200 2> /dev/null
    ip route flush cache
    ip rule del from 192.168.0.200 table 200
    EOF
    chmod +x /jffs/route-down.sh
    Finally, add the following directives to the OpenVPN server Custom Config field.

    Code:
    script-security 2
    route-up /jffs/route-up.sh
    route-pre-down /jffs/route-down.sh
    When the OpenVPN server starts, it will create the PBR data structures. And now the local routing tables of the tomato router are configured to route all traffic sourced from 192.168.0.200 over the VPN rather than the WAN. You can inspect the changes w/ the following commands.

    Code:
    ip route show table 200
    ip rule list
    When the replies get back to the OpenVPN client side of the tunnel, the DNAT will be undone and the source IP of the reply packets will be changed from 192.168.0.200 back to 1.1.1.100.

    That should do it.
     
  14. eibgrad

    eibgrad Network Guru Member

    P.S. As I mentioned before, you may want to use a PTP OpenVPN tunnel via scripting to make things a bit simpler (no tls, no certs, no keys, etc.). And I assume you'll have to script the OpenVPN client side on the VPS at a minimum. A PTP tunnel is not quite as secure as multi-client to server config (as described in that link I provided), but given you weren't encrypting the original design anyway, a PTP tunnel is probably sufficient. It doesn't even have to be encrypted. It could be in the clear if you want (for performance reasons). The primary benefit of using OpenVPN is to get the public IP space removed from between the VPS and the tomato router. That's what's making it difficult to solve the problem. And the tunnel (which runs in the private space) takes care of that problem.
     
  15. Sean B.

    Sean B. Network Guru Member

    Maybe I'm not following correctly, as there's been a lot of stuff tossed around in this thread. But won't this route all traffic for non-local interfaces/internet from the windows server over the VPN when it's up? Which would break an established connection if the VPN goes up/down. And break any new connections if there's a port forward from the tomato router to the windows server for clients that are WAN side yet not behind the linux server. Perhaps not an issue for the use case, but again, hard to follow.

    There's an alternative here that departs from the current thought process, if offered by OP's ISP(s). Run IPv6 and get rid of NAT entirely. Running dual stack would allow for the network to remain as it currently exists with IPv4, yet add globally routable IPv6 IP's to all clients, which can then be used for inter-site routing without the hassle/annoyance of NAT.
     
    Last edited: Apr 23, 2019
  16. eibgrad

    eibgrad Network Guru Member

    One of the problems here is that we're getting only a keyhole view of the OP's intent. As you've stated, if that Windows server will also be accessed over the WAN via port forwarding, then yes, what I'm proposing *would* break those port forwards. And I tried to anticipate that issue by asking the following of the OP in post #9.

    Also, if that Windows server needs to *initiate* outbound connections to the internet, those will have to be routed over the VPN and through the VPS as well. But here again, we don't have sufficient information to know if that is or isn't an issue.

    There is no perfect solution here given the OP insists on routing the client via the VPS, and insists on the Windows server seeing the public IP of the client. Compromises are inevitable. The OP will need to decide if they are acceptable.

    P.S. I suppose one way that would permit the Windows server to also use the WAN is to bind the server and router to a secondary local IP network (e.g., 192.168.1.200). And then port forward to that IP address from the VPS, and use PBR based on that IP address as well.
     
    Last edited: Apr 23, 2019
  17. eibgrad

    eibgrad Network Guru Member

    FYI, I spent a few hours this evening reworking some OpenVPN PTP scripts I had created some time ago for my OpenVPN performance testing. At that time I was using a VPS for the OpenVPN server, and my tomato router as the OpenVPN client. For the OP's purposes, I had to make a few changes, like switching the roles (i.e., the VPS is now the OpenVPN client and the tomato router is the OpenVPN server). The hard part wasn't so much the OpenVPN scripting, but just getting the VPS configured in general. I had to start from scratch because the current VM on my VPS is stuck in startup mode (just spins and spins, and no way to kill it).

    I've confirmed it works. I just wanted to do a sanity check. It's one thing to propose something off the top of your head, but you never know what you might have forgotten or missed until you see it in action.

    What I'll do is post my scripts in the morning (it's late evening here), and also explain how I configured my VPS. And if the proposed solution doesn't cut it for the OP, we'll consider other options.
     
  18. Sean B.

    Sean B. Network Guru Member

    While I'd have to do some testing to find out the exact syntax and packet flow, I believe it should be possible to use the connmark target to mark packets coming in over the VPN, restore the mark on outbound traffic from the windows server which matches in the conntrack list, and then use an ip rule to point that traffic at a lookup table which defaults the route back over the VPN. Thus eliminating the issue of all traffic being routed over the VPN, as from what I can tell the windows server side will never be the one starting a connection that traverses the VPN, so it should be safe to only route traffic out based on the traffic that came in.
     
    Last edited: Apr 23, 2019
    eibgrad likes this.
  19. eibgrad

    eibgrad Network Guru Member

    That's a really good idea, Sean B. That's one of those details I hadn't thought about. I even do the same thing in my tomato advanced PBR script, which has been around for some time.

    https://pastebin.com/GMUbEtGj

    (search for CONNMARK)

    What surprises most ppl is merely installing the script fixes the problem of remote access over the WAN to devices on the LAN that are otherwise using the router's OpenVPN client as their default gateway. And I do it by marking connections rather than just packets. So if someone port forwards via the WAN, the connection is marked so the replies are automatically routed back out the WAN. Same thing happens if you remote access over the VPN (provided your VPN provider allows port forwarding). It's routed back out the VPN.

    One downside though is sometimes this can create conflicts w/ other parts of the system that are also marking packets (e.g., QoS). My current approach doesn't have such conflicts. That's why I also have a basic PBR script (https://pastebin.com/xEziw8Pq) that's not dependent on marking packets.

    So that's a worthy enhancement. But for the moment, let's see if what I have so far is sufficient. It's mostly a POC (proof of concept) at this point for the OP. If it isn't, we can then decide whether to add your suggestion.

    Scripts will be posted shortly, w/ instructions.
     
    Last edited: Apr 23, 2019
  20. eibgrad

    eibgrad Network Guru Member

    Here are the scripts.

    https://pastebin.com/mzDqP9DD (openvpn ptp tunnel - server)
    https://pastebin.com/gwQQtwrE (openvpn ptp tunnel - client)

    Realize there is no additional NAT'ing taking place beyond what would be typical of any NAT router performing normal functions. We're only using DNAT for the port forwards, and NAT'ing the local network of the Windows server over the local network of the VPS (the latter being required when the Windows server needs internet access via the VPN). The whole point of this exercise is to remove NAT as much as possible for what is presumably an IPv4 configuration. Even if this was an IPv6 configuration, it still makes sense to secure the connection between the VPS and the tomato router w/ a VPN.

    Each script uses the same installation methodology. In the case of the server script, you open a shell (telnet/ssh) on the tomato router w/ Putty and copy/paste the script into the terminal window (after copy, just right-click in the window). The script will create a bunch of other files/scripts in the /tmp/ovpn_ptp folder, start the OpenVPN process, and immediately attempt to ping the OpenVPN client. Now open a shell (ssh) on the VPS and do the same thing w/ the client script. The script will similarly create a bunch of other files/scripts in the /tmp/ovpn_ptp folder, start the OpenVPN process, and immediately attempt to ping the OpenVPN server.

    Of course, you will need to slightly modify each script for your personal needs. The default settings use an obscure port for the OpenVPN server (22810), which you can change (just keep each script in-sync). And you'll obviously need to change the remote ip to your tomato router's public IP on the WAN. In my case, I used another router behind my tomato router as the target of remote access, so I could monitor the individual connections being made into that router, and thus confirm the presence of the public IP of any remote client of the VPS. So change the EXT_PORT, INT_IP, and INT_PORT to that of your Windows server.

    And btw, every PTP tunnel should obviously use its own unique static key. The one currently installed will work, but can easily be replaced by going to the same shell on either the tomato router or VPS and issuing the following command.

    Code:
    openvpn --genkey --secret static.key
    Then replace the current static key in the scripts w/ the contents of that file (static.key).

    As I said, the burdensome part for me was just getting the VPS up and running, and configured to my liking. I used the following script to create the /etc/rc.local file (which autostarts on reboot) on the Ubuntu VM (18.04 if it matters).

    Code:
    cat << "EOF" > /etc/rc.local
    #!/bin/sh
    # /etc/rc.local
    
    # Default policy to drop all incoming packets
    iptables -P INPUT DROP
    iptables -P FORWARD DROP
    
    # Accept incoming packets only from established connections and ssh
    iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
    iptables -A INPUT -p tcp --dport 22 -j ACCEPT
    
    # Accept incoming packets only from established connections
    iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
    
    # rc.local needs to exit with 0
    exit 0
    EOF
    chmod +x /etc/rc.local
    My no means am I suggesting this is a complete and comprehensive firewall. I just wanted a quick and dirty setup so when the OpenVPN server is started and adds its own firewall rules, it all works together.

    As long as you see each side of the tunnel successfully pinging the other side, you know at least the tunnel works. You may still have some issues getting remote access working, depending on whether you have all your other configuration options configured properly.

    As written, the target of remote access (Windows server in the case of the OP) is required to use the VPN for its own outbound internet connections. Whether that is or isn't a problem needs to be communicated by the OP. And if it is, we could consider Sean B.'s suggestion of marking connections (w/ the caveat it may be incompatible w/ QoS, or anything else also marking connections/packets (e.g., Routing Policy on the OpenVPN clients of the tomato GUI)).

    It does work here w/ my tomato router and VPS, whether for remote access, or the target needing to initiate connections over the VPN (you'll know it's using the VPN if you go to the Windows server and check your public IP).

    As an aside, it is possible to create a completely insecure, unencrypted, unauthenticated tunnel using this setup. Just comment out the static key and/or set the cipher and auth to none. You'll get a prominent warning in the syslog of the tomato router that strongly suggests you reconsider the current configuration. As I said, I was using similar scripts (but reversed roles, the tomato router was the OpenVPN client, and the VPS was the OpenVPN server) to test the performance of the OpenVPN clients on tomato (and dd-wrt and Merlin as well). I used an in-the-clear tunnel to confirm the performance hits we see w/ the OpenVPN client are NOT due primarily to the lack of hardware assisted encryption. It made no difference whether I did or didn't use encryption, it still sucked. :)

    Anyway, that's besides the point at the moment. I figured if the OP wasn't using any protection between his VPS and the tomato router w/ his original design, a PTP tunnel was certainly no worse, and even a bit better, w/ a multi-client to server config (and all the other baggage that brings) being the most secure option.

    Questions, suggestions, etc., are welcome from all.
     
    Last edited: Apr 24, 2019
  21. Sean B.

    Sean B. Network Guru Member

    I need to get a second hand ARM router to use for experiments. I can only break the internet connection so many times in a day before the wife an kids grab pitch forks.
     
    eibgrad likes this.
  22. eibgrad

    eibgrad Network Guru Member

    That's why I picked up several cheap ARM routers from various Slickdeal.net offers. T-Mobile has been repeatedly dumping the TM-AC1900 (which is nothing more than an RT-AC68U in disguise) for ~ $40. Must have seen at least 15 or more such deals in the past couple years. With some effort, they can be updated w/ any third-party firmware. Here's the latest (although currently expired) deal.

    https://slickdeals.net/f/13002436-t...1900-gigabit-router-pre-owned-40-free-s-h?v=1

    Wait long enough, and it will come back again. And although it says refurbished, 99% of the time you get a brand new, in the box router (I have 5 of them at this point, all were new).

    I have plenty of other older routers (mostly mips) as well, all running various firmware, including dd-wrt, freshtomato, shibby tomato, merlin, etc. And all have their WAN patched to the primary router, and firewall disabled, so I don't have to mess w/ the primary router (at least most of the time), and I can access them from the primary network. IOW, I don't usually need to patch a client to those routers just to gain access, although I do on occasion to test the client itself.

    A lot easier to deal w/ user issues in these forums when you don't have to mess w/ your primary router. Learned that lesson years ago.
     
    Sean B. likes this.
  23. eibgrad

    eibgrad Network Guru Member

    Just as an aside, I'm using Scaleway as my VPS.

    http://scaleway.com

    It's a "pay only for what you use" type of service. They had a special deal this month; free up to the first 100 euros (they're Paris and Amsterdam based). You can install a pretty minimal but still effective Ubuntu 18.04 build there for as little as 3 euros/month. But that's the most you'll pay. If you only use if for a few hours or days, it could be considerably less. IOW, create your VM, do your testing for a few hours, then delete the VM. But if you want to make it persistent, it will max out at about 3 euros for the month.

    I'm using the DEV1-M build at the moment, which is 7.99 euros/month, but that's only because it's free w/ the current special offer. The DEV1-S build (3.99 euros/month) would have been sufficient for the current task.
     
    Last edited: Apr 24, 2019
  24. Sean B.

    Sean B. Network Guru Member

    Have another option for routing only the correct traffic over VPN. Tested the flow up to the point of leaving the WAN, as I wasn't using an outside client. The concept uses recent extension rather than conntrack.

    1. Add source IP of all traffic destined for the windows server coming in from the VPN to a list, if IP already exists in list, update existing entry.
    Code:
    iptables -t filter -I FORWARD 1 -i tunX -d 192.168.1.200 -m recent --name vpnlist --set -j ACCEPT
    2. Create custom chain in filter table for marking packets
    Code:
    iptables -t filter -N VPNMARK
    3. Check the destination IP of packets coming from the windows server for a match to source IP's saved in the recent list, jump any that do to the custom chain
    Code:
    iptables -t filter -I FORWARD 2 -s 192.168.1.200 -m recent --name vpnlist --rcheck --rdest -j VPNMARK
    4. Mark all packets through the chain for PBR routing to use
    Code:
    iptables -t filter -I VPNMARK 1 -j MARK --set-mark 3
    iptables -t filter -I VPNMARK 2 -j ACCEPT
    Create PBR rule/table using the fwmark 3, default route to VPN.
     
    Last edited: Apr 25, 2019
  25. ras07

    ras07 Network Guru Member

    Sorry for going dark; I've been kind of held up testing this due to troubles getting OpenVPN working on FreshTomato (I was short of NVRAM). (As a complete aside, elliptical certs work with OpenVPN on FreshTomato! EC certs are about 60% the size of RSA certs, plus you don't need DH params, so it saves a lot of NVRAM space.)

    BTW I'm also using Scaleway, although their internal networking is tripping me up. Their VPS doesn't use the external IP directly, it has a 10.x.x.x IP. So I sometimes get confused over when I need to specify the listed external IP and when I need to use the 10.x.x.x IP. (I was using Vultr earlier and they don't have this complexity - may go back to them.)

    I haven't yet fully digested the later posts in this thread, but I will work on that now that I have OpenVPN running. But in the meantime, I hope this will be a simple question:

    I configured my router as an OpenVPN (TUN) server, and both the Linux and Windows machines as OpenVPN clients. The VPN subnet is 10.0.0.0/24, and I have the router configured to push that route (push "route 10.0.0.0 255.255.255.0" in the custom config). The Linux (10.0.0.6) and Windows (10.0.0.14) machines can talk to each other and the Linux machine can access the Windows machine over the 10.0.0.x subnet. So I thought I should be able to NAT over the 10.0.0.x network, like so:

    Code:
    iptables -t nat -A PREROUTING -p tcp --dport 1234 -j DNAT --to-destination 10.0.0.14:5678
    iptables -t nat -A POSTROUTING -p tcp -d 10.0.0.14 --dport 5678 -j SNAT --to-source 1.1.1.100
    However, this does not work. Why is that?
     
  26. eibgrad

    eibgrad Network Guru Member

    As I originally described this config, there is only *one* OpenVPN client; the VPS. The Windows server is completely unaware of any VPN being in the mix. The remote client connects to the VPS ip : port (1.1.1.100:1234, using your example) and is port forwarded to the OpenVPN client on the VPS and over to the OpenVPN server on the tomato router. From there, the traffic is forwarded from the OpenVPN tunnel and to the Windows server on the local network.

    Review my OpenVPN PTP scripts! I show you exactly how to do it.

    https://www.linksysinfo.org/index.p...aintain-the-originating-ip.74555/#post-304459
     
  27. ras07

    ras07 Network Guru Member

    Got it; I will work through your scripts. Was just curious why what I did didn't at least route (I understand why it might lose the source IP, but it didn't have any connectivity at all, which was unexpected).
     
  28. Sean B.

    Sean B. Network Guru Member

    Where does the 1.1.1.100 IP fit into what you were trying to do? The first rule you have will change the destination IP/port to 10.0.0.4:5678 for any packet that has the destination port of 1234, IE: doesn't matter what host sent it.. it will now go to 10.0.0.4:5678. The second rule you have will change the source IP of any packet destined for the 10.0.0.4 host on port 5678 to 1.1.1.100. These rules only change one side of the flow ( I use the word "flow" loosely, because these rules could mix in traffic that wasn't part of the intended flow to begin with as they are too indiscriminate ) . From host A to host B ( first changed the destination IP, then changed the source IP.. all on only one side of the connection ), but does nothing for host B to host A. When you change source/destination with NAT, you need to remember that the host who originally sent the packet has no idea the packets are being messed with. This means that in order for the connection to work, you have to change the returning packets to match what the original host will be expecting. IE: if host A tried to connect to another host at IP 2.2.2.2 port 1234.. and you DNAT that traffic to 10.0.0.4 port 5678, the original host will receive a response from IP 10.0.0.4 port 5678 and have no clue wtf that host is trying to talk to him and drop the packets. Or better yet, if host A tries to connect to IP 2.2.2.2 port 1234 and you both DNAT it to 3.3.3.3:5678 as well as SNAT it to a source of 4.4.4.4:4444 , the host 4.4.4.4 will receive the return traffic from 3.3.3.3 even though host 4.4.4.4 never took part in any of this. The return packets must be DNAT'd so they make it back to the original host as well as SNAT'd so they are from where the originating host would be expecting them to come from.
     
    Last edited: Apr 27, 2019
  29. ras07

    ras07 Network Guru Member

    I'm still not able to get these to work. The tunnel is being created and the pings being executed by both client and server are working fine.

    Q1: From the Windows machine at 192.168.0.200 I can ping the router's TUN address (10.8.0.1) but not the Linux server's TUN address (10.8.0.2). Should I be able to?

    Q2: Likewise, should I be able to ping 192.168.0.200 from the Linux box? (I cannot.)

    Also, one point of clarification: in my example where the Windows server is at 192.168.0.200, that's the IP that should be entered at both Line 6 of the server script and Line 11 of the client script, correct?

    EDIT: Also, with the script running on the router, the Windows box at 192.168.0.200 loses Internet connectivity.
     
    Last edited: Apr 29, 2019
  30. eibgrad

    eibgrad Network Guru Member

    Well that's a major accomplishment at this point.

    Yes. Presumably the Windows server is using the same tomato router that's hosting the OpenVPN server (and the tunnel network) as its default gateway. So if that Windows machine attempts to ping the tunnel, it should send it the tomato router, which should then reply back to the Windows server.

    Yes. That's the first thing that has to be possible if you expect the remote client of the VPN to likewise be port forwarded to that same Windows server.

    Yes.

    One possibility is that you didn't NAT the 192.168.0.200 network over the VPS's local network. When using Scaleway, I noticed the VM was on a private network. But you still need to NAT traffic from the 192.168.0.200 over that local network so the upstream router will see the local IP of your VM and NOT the 192.168.0.200 ip of the Windows server.

    I included that NAT rule in the OpenVPN client script, but perhaps there's something different about your VPS configuration that could explain the problem.

    With the system up and running, and successfully pinging across the tunnel, dump the relevant data structures on both the VPS and tomato router to make sure they are configured as we presume them to be. That will probably reveal the problem.

    Code:
    # OpenVPN server dump
    ifconfig
    iptables -vnL INPUT
    iptables -vnL FORWARD
    ip route show table main
    ip route show table 200
    ip rule list
    
    # OpenVPN client dump
    ifconfig
    iptables -vnL INPUT
    iptables -vnL FORWARD
    iptables -t nat -vnL PREROUTING
    iptables -t nat -vnL POSTROUTING
    ip route show table main
    If you want to obscure public IPs and similar personal information, that's fine, but do so consistently, and make it obvious.
     
    Last edited: Apr 30, 2019
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice