Haproxy gateway settings - client and server are on the same subnetwork - load-balancing

I'm trying to setup a haproxy gateway between server and client for full transparent proxy like below diagram. My main aim is to provide load balancing.
There is a simple application that listens port 25 in the server side. The client tries to connect port 25 on the gateway machine, and haproxy on the gateway chooses an avaliable server then redirects the connection to the server.
Network analysis of this approach produces tcp flow like diagram: The client resets the connection at the end since it doesn't send a syn packet to the server.
Is this haproxy usage true and my problem related configuation? Or should the client connect to the server directly (This doesn't make much sense to me but I'm not sure actually. If this is true then how haproxy will intervene the connection and make load balancing)?
EDIT:
I've started to think this problem is related to routing and NAT on the gateway. All of these three machines are in same subnetwork but I've added routes to the gateway for both client and server. Also rules on the gateway are:
iptables -t mangle -N DIVERT
iptables -t mangle -A DIVERT -j MARK --set-mark 0x01/0x01
iptables -t mangle -A DIVERT -j ACCEPT
iptables -t mangle -A PREROUTING -p tcp -m socket -j DIVERT
iptables -t mangle -A PREROUTING -p tcp --dport 25 -j TPROXY \
--tproxy-mark 0x1/0x1 --on-port 10025
ip route flush table 100
ip rule add fwmark 1 lookup 100
ip route add local 0.0.0.0/0 dev lo table 100
Now the question is what should I do in the gateway to change "syn-ack (src: S, dst: C)" to "syn-ack (src: GW, dst: C)"?

Here is the definition of my situation.
Here comes the transparent proxy mode: HAProxy can be configured to spoof the client IP address when establishing the TCP connection to the server. That way, the server thinks the connection comes from the client directly (of course, the server must answer back to HAProxy and not to the client, otherwise it can’t work: the client will get an acknowledge from the server IP while it has established the connection on HAProxy‘s IP).
And the answer is to set ip_nonlocal_bind system control.

Related

iptables FORWARD rule blocking return traffic

I have a VM running OpenVPN with client-to-client disabled and I need some specific forwarding rules. IP forwarding on the VM is turned on.
The OpenVPN base network is 172.30.0.0/16 and that is further subdivided into /24 subnets with their own rules.
172.30.0.0/24 should have access to all the clients. The rest should not. I have 2 subnets defined at the moment; 172.30.0.0/24 and 172.30.10.0/24.
Following the suggestion at the bottom here;
https://openvpn.net/community-resources/configuring-client-specific-rules-and-access-policies/ - I set up my rules as follows;
iptables -A FORWARD -i tun1 -s 172.30.0.0/24 -j ACCEPT
iptables -P FORWARD DROP
This does not work. If I add a -j LOG at the top, I can see that traffic from my client at 172.30.0.1 connects fine to the client at 172.30.10.3, but all traffic it sends BACK is blocked.
If I set the policy to ACCEPT everything works and I can connect to the client just fine, so this is not a routing problem.
How can I set this up? And why doesn't the suggestion in that OpenVPN guide work?
I solved this by adding
iptables -A FORWARD -i tun1 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
which allows established connections to return. Everything works as desired now.

Change source and destination address iptables

I need to transform destination IP of packets when they arrive from our client, ands also transform the source IP of packages leaving our network to the client's network.
I have IPSec VPN tunnel with a client on a Linux box. The machine has two interfaces with the following config:
eth0: 172.15.100.5
eth1: 172.15.100.15 (public IP 33.x.x.x)
Application server is 172.15.100.50.
Clients IP: 10.26.18.38/32
Client cannot use our internal IP 172.15.100.50 to talk to the application via the tunnel. Instead, they will send traffic through the VPN to 172.20.100.55 (which is not our IP) and they need us to response with source IP as 172.20.100.55.
My thinking is that I should be able to use iptables POSTROUTING and PREROUTING transform destination IP of incoming traffic from 10.20.100.55 to 172.15.100.50 (application server), and outgoing traffic from our network application server IP 172.15.100.50 to 10.20.100.55. However, I am not sure of the correct way to achieve this.
iptables -t nat -I PREROUTING -i eth1 -d 10.20.100.55 -j DNAT --to 172.15.100.50
iptables -t nat -I POSTROUTING -i eth0 -d 10.26.18.38 -j SNAT --to 172.20.100.55
I have monitored traffic with tcpdump and on the application server, but it would appear my NAT rule is not working.

Configuring IP Tables

I want to make sure that the only network traffic on my linux CentOS server is my own.
All my server runs is a Tomcat instance with one servlet. This servlet takes a parameter, which is a URL to download. It will download from that url, and pass the contents back to the calling program through the usual http response.
I want to block all network traffic to this server except
1) Ability to ssh
2) Ability to download from host abc.xyz.com
3) Ability for server with IP 111.222.333.444 to download from me
Can someone please tell me the commands to do this in iptables? I tried finding this out myself but I was a bit out my depth with the lingo.
thanks
Configuring a firewall is simple, first of all select what ports you want to be open.
For example Webserver ports:
iptables -A INPUT -p tcp -m tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp -m tcp --dport 443 -j ACCEPT
For example SSH port:
iptables -A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
In any way your server is able to download files from other server/hosts.
3) Ability for server with IP 111.222.333.444 to download from me
I suppose that must be port 80, (or any port where the server is downloading from) if your uploading files to your website.
After these steps you need to look if the firewall is configured right:
iptables -L -n
If it's looking good then you're able to save your iptables, and restart the service.
If there is any problem configureren your firewall, please let me know.

with iptables forwarding port to other client but with recognition of original sender ip

I have a firewall (based on iptables) at dedicated ubuntu server.
I have several LAN Clients.
At one of my LAN Clients I am running software where I can restrict acces based on IP.
For me it is important that I can restrict that by using WAN IPs so not LAN IPs.
I have configured my firewall so that a/one port is forwarded to a LAN client which work good (solution found at stackoverflow). So far no problems.
However at the LAN client I do not see the IP of external sender but - I think due to the forwarding - the client sees that the packet is coming from my LAN server.
Question is: how to forward a port on my server to another LAN IP with different port, but so that the LAN client recognizes the external IP of the packet.
Lets make it more clear:
server LAN IP: 192.168.1.10
server port: 8080
should be forwarded to:
client LAN IP: 192.168.1.20
client LAN port: 8000
With iptables I have:
iptables -t nat -A PREROUTING -p tcp -i eth0 --dport 8080 -d 192.168.1.10 -j DNAT --to 192.168.1.20:8000
iptables -A FORWARD -p tcp -d 192.168.1.20 --dport 8000 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
iptables -t nat -A POSTROUTING -p tcp --dport 8000 -d 192.168.1.20 -j SNAT --to 192.168.1.10
As written that works, but when f.i. someone at IP 88.77.66.55 sends a packet then my LAN client (192.168.1.20) sees that the packet is coming from my LAN server (192.168.1.10) and unfortunately not from 88.77.66.55.
Can I fix that...?
Your last rule is the same as a MASQUERADE rule.
eg:
iptables -t nat -A POSTROUTING --out-interface eth0 -j MASQUERADE
With MASQUERADE or SNAT, you are modifying the source-IP address as it goes through the first server. The 2nd server sees the packet and sends it's response back to that IP, which is then sent back to the client.
However, the server sees request as coming from 192.168.1.10 - because that's where it's coming from.
client > gateway > iptables-router > server (sees .10) > iptables-router > gateway > client
If you remove the MASQUERADE/SNAT, the server sees the real IP, but when it sends the reply, the packet is going to it's default gateway (default route) which is probably your router or a gateway at your data center. The client gets a response back from an IP address it doesn't know about, and doesn't know what to do with it, so it looks like it's not working. Alternatively, the gateway/rputer sees a SYNACK with no associated connection and drops the packet.
client > gateway > iptables-router > server > gateway (DROP) or > client (DROP)
If you want the server to get the real IP of the client, here are two common ways to make it work:
Set the gateway (default route) of the server to the IP address of the iptables machine (ie: the machine you are running these iptables rules on). In this case, the server sends all external traffic (ie: a response to a random IP address from the internet) to the MAC address of the iptables machine, which is waiting for a reply. iptables will send it back to the client. The webserver machine is behind the iptables machine, using the iptables machine as a router.
client > gateway > iptables-router > server(real IP) > iptables-router > gateway > client
Use an HTTP proxy like nginx which will work the same way you have it working now, with the client only seeing the internal .10 address. However, because it's a proxy, it can send an HTTP header like X-Original-IP-Address: 123.456.789.012 containing the real IP address of the client.
client > gateway > iptables-router > server (sees X-Original-IP header) > iptables-router > gateway > client
Best Regards,
Neale
Let us define:
{source address} - packet sender (some remote address)
{interface address} - packet receiver (firewall external address)
{local address} - packet end point receiver local network address
{local gateway} - firewall local address
{proto block} - IP protocols limitation (i.e. -p tcp -m tcp --dport xxxx)
1. If you want the client to see ip address of packet source - do that:
IPTABLES -t nat -A PREROUTING -s {source address} -d {interface address} {proto block} -j DNAT --to-destination {local address}
IPTABLES -A FORWARD -d {local address} -j ACCEPT
Do not forget to make:
echo "1" > /proc/sys/net/ipv4/ip_forward
It will enable packets forwarding.
In this case, your end point will see original ip address, however, it will try to respond to default gateway, if this address is not in local network range, add:
route add {source address} gw {local gateway}
this will tell your endpoint to send packets for {source address} via {local gateway} (or reply back).
2. You do not want endpoint to see original ip address and do not want to modify routing tables, then add
IPTABLES -t nat -A POSTROUTING -s {source address} -j MASQUERADE
In this case, LAN client will see only {local gateway} address.
In any case, do not forget to masquerade all packets that are going from your local network to remote addresses by:
IPTABLES -t nat -A POSTROUTING !-d 192.168.0.0/16 -j MASQUERADE
You want to keep source address and destination address for further processing. In this case, your {local gateway} will be just a part of packet routing and {local address} has to be just a next hop - use policy routing for that.
First, add your own routing table with lower than 252 tag to /etc/iproute2/rt_tables
Then - you can add rule for {source address} directly to rules set or mark packets from {source address} - both methods will lookup your custom routing table for that packets:
ip rule add from {source address} table custom_table
or
iptables -t mangle -A PREROUTING -s {source address} -j MARK --set-mark 1
ip rule add fwmark 1 table custom_table
And then, make {local address} next hop gateway for these packets:
ip route add default via {local address} table custom_table
Of course, POSTROUTING chain will be applied just before packet exit and you can shape your source address if needed.
Just remove last rule (do not do SNAT).
Or restrict SNAT alloving only masquarading of your LAN clients by adding -o eth0 condition (assuming eth0 is external interface):
iptables -t nat -A POSTROUTING -p tcp -o eth0 --dport 8000 -d 192.168.1.20 -j SNAT --to 192.168.1.10

Iptables : forward port from another server than the gateway

Here is the situation.
We have multiple server on our intranet 192.168.1.0/24
One of them is the default gateway for all of them and have two interfaces ($GATEWAY_INTERNAL_IP and $GATEWAY_EXTERNAL_IP).
We have also another server PUBLICHOST2 which has two IP as well $PUBLICHOST_EXTERNAL_IP and $PUBLICHOST_INTERNAL_IP.
We have a third server SERVER which have only one IP $PRIVIP and bind on port $PORT.
What we want is to be able to forward port $PORT on $PUBLICHOST_EXTERNAL_IP to host SERVER on $PRIVIP.
But when we do the port forwarding using iptables on PUBLICHOST2, SERVER receive the request but the response goes through the gateway and the connection is not successfull.
How can we properly do the setup so that the response can go back through PUBLICHOST2 ?
Thanks
You may need to set forwarding on for the interface. Try tne command.
sysctl -w net.ipv4.conf.eth0.forwarding=1
If you need additional help look for documentation on routeback or the Shorewall FAQ.
Well here what happens:
Client1 sends a request to PublicHost
The requests arrives and the iptables rules redirects the traffic (PAT) to the Server on the correct AppPort
Server sends back a reply to Client1 which will be routed by Gateway
Gateway is doing NAT and replaces the source IP with it's own
Client1 or Client1sGateway receives the IP packet with Gateway as the source but it expected PublicHost's IP in the source field of the IP packet.
Eventually Client1 resends the SYN/ACK (except if you're using a synproxy) to PublicHost and then drops the connection when whatever network related timer expires.
Now if you want to fix this, you should route all TCP traffic going OUT of Server and with a source port of AppPort to PublicHost.
If this doesn't work, PublicHost is not properly configured. Be sure to test the configuration with tcpdump.
I've been trying to do something similar. After running through a bunch of tutorials that never seemed to work until I Wiresharked the connection to discover that the destination address was still set to the external IP address, (exactly like you've described), I tried using the POSTROUTING chain to change the source IP address to that of the server:
iptables -t nat -A POSTROUTING -p <tcp/udp> --dport <destination_port> -j SNAT --to <$PUBLICHOST_INTERNAL_IP>
After I added that rule, the connection was forwarded into the private network and the response packets retraced the same path back to the client, rather than through the network gateway. I'm not positive what allowed the response packets back out through the firewall server, but I think it was because of the rule I already had on the INPUT chain to allow established connections:
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
The thing to be sure to keep in mind with this solution is: if you ever change the firewall server's internal IP address, then you will need to update the above POSTROUTING rule. (Needless to say, it's probably best if the firewall server has a statically assigned internal IP address).