Ping through an LXC container - iptables

I'm dealing with LXC, iptables and route, and at this point I'm not even sure what I'm doing anymore. For the sake of simplicity, every policy in iptables is set to ACCEPT and forwarding is set to 1 in sysctl.conf in each host or container.
My goal here is to be able to pass a ping request through an LXC container, from outside of its host. Let me clarify this:
Let's say I have a client C, who wants to ping a server S, but I have a gateway G in between, and an LXC container L within G.
C (eth0 192.168.0.3/24) <---> (eth0 192.168.0.2/24) G (eth1 192.168.1.3/24) <---> (eth0 192.168.1.4/24) S
then, inside G we would have :
(eth0 192.168.0.2/24) <---> (virbr0 10.0.0.2/24) L (virbr1 10.0.1.3/24) <---> (eth1 192.168.1.3/24)
So basically, I'd like to ping S from C but in such a way that the request must transit through L (and therefore through G), using iptables and route.
Hope you can help me out !

Could you share your reason for doing this? Is this for monitoring? Routing through a NAT is unnecessarily convoluted.
I suggest setting up a bridged network, rather than a NAT-ed one, where:
virbr0 is bridged with eth0
virbr1 is bridged eth1
This way, your LXC host can sport an IP address of 192.168.0.x and 192.168.1.x (ie. in the same subnet as eth0 and eth1).
Once that is done, create routing entries in both the server and client, using the LXC host as the router. Essentially L replaces G.
Let's assign 192.168.0.10 and 192.168.1.10 to L. The routed network will look like this:
C (192.168.0.3) <--> (192.168.0.10) L (192.168.1.10) <--> S (192.168.1.4)
Let me know if this works for you before I post the full answer. It's quite a bit of configuration.

Related

Bulding an SSH tunnel

I have three hosts: A, B, C. B can connect to C through ssh, via port 221. A cannot connect to C because it's behind a router, but can connect to B through ssh. What I need, is to connect from A to C.
The situation is summarized below:
A -- p22 ---> B OK
B -- p221---> C OK
A -- p???---> C not working
I have tried many variations of ssh tunneling but looks like I don't get how tunneling works. Also, I have no root privileges on any of the hosts, therefore I cannot do port forwarding on port 22. I am therefore not sure this tunneling can be done at all. If it can, however, I would appreciate the exact commands to run on each host so that I can finally ssh from A to C.
While you could set up an explicit tunnel in this situation, it's much more convenient to use the -J option
ssh -J B -p 221 C
or the ProxyJump option explicitly
ssh -o ProxyJump=B -p 221 C
ssh will first connect to B for you (prompting for a password if necessary), then connect to C from B. From your point of view, you will have connected directly to C.
The idea of ssh -L local_port:another_host:destination_port user#host is to say a/ start listening locally on local_port b/ connect to remote host (as usual), and once you're there, connect to that another_host and c/ forward everything you will receive locally to that another host's destination_port
so, I would try the following (from host A)
ssh -C -N -L 2222:C:221 user#B
then from another terminal
ssh -p 2222 user#localhost
I did not test the above. Happy to dig deeper if required.
Here is the human readable explanation (hopefully) :
starting from host A
ssh, connect as user on host B (no port specified as 22 is the default)
-C compress all content in transit in the tunnel
-N says to not open a tty (interactive) session on host B
-L says "once you're on B, start listening on this host (A) on port 2222 (as you are not root) and forward everything to C, port 221"
If you're using password authentication, it should work. Certificate authentication would require a bit of additional configuration on B to correctly forward your certificate to C (which exact syntax I don't remember right now)

Emulating a virtual host for UDP communication

First of all this question is not about virtual host in Apache.
I have a network with the following address: 1.1.1.0
I have several host on this network: 1.1.1.1, 1.1.1.2, 1.1.1.3 and 1.1.1.4
The first host send a broadcast UDP paquet answer and expect other host to answer him.
Is it possible for my dev machine (1.1.1.4) to emulate the following virtual host : 1.1.1.5, 1.1.1.6, etc. ?
I'm using QUdpSocket from Qt 5.2.1 on MacOS 10.9 but I am open to any other tech that would help me do the trick.
It depends on you OS.
On linux, you can create multiple virtual network devices, and bind each of those devices to a different network address. The virtual network devices have the name of a real device with a :xxx numeric suffix. For example, if your primary network device is eth0, you can run the command
ifconfig eth0:1 1.1.1.5
to create the virtual device eth0:1 and bind it to the address 1.1.1.5. This is only temporary (it will go away when you reboot); if you want it to come back when you reboot, you can edit the `/etc/network/interfaces file to look something like:
auto eth0
iface eth0 inet static
address 1.1.1.4
netmask 255.255.255.0
gateway 1.1.1.1
auto eth0:1
address 1.1.1.5
netmask 255.255.255.0
the lack of a gateway in the eth0:1 part means that it won't use this interface for routing, so it just exists for receiving packets and explicit binding to an ip address.
Install VirtualBox (here) and make a tiny disk image big enough for a small Linux distro. Run several copies, each one at a different IP address and run a tiny netcat script in each one that listens and sends replies.
#!/bin/bash
while :
do
command=$(nc -ul 1234)
process $command and reply
done
Or, read this and go with Chris's idea which is lighter weight on resources!

ssh tunnelling port forwarding

I have three computers, A, B, C. A is the computer I'm working on, C is the remote computer I'd like to access. However C can only be accessed through B. Only B has a ssh server, and only A has a ssh client.
What command am I to use (preferably on A) so that I can connect to C (port 80) through B ? For example B should forward all incoming port 12345 to C:80.
I know this is a common question and I found a ton of commands on google but none seemed to work.
Once it is set up, I'm supposed to just use localhost:5678 on A, which connects to B:1234, and then forwards to C:80.
Thanks.
You need to use remote port forward:
From A run
ssh -R *:1234:C:80 you#B
Then you can access C by typing B:1234, but this also requires setting GatewayPorts to yes in /etc/ssh/sshd_config , and the restart sshd (this tells C to listen to all IP addresses, not just local IPs, so it can be accessed from the outside)
Once you logout from B, it will also disable the tunnel to C.

Iptables sniffing traffic not sent to local machine

I have a switch configured to mirror all traffic to an ethernet interface of a server. I can actually see the packets received with tshark, tcpdump, etc, but iptables doesn't seem to see this traffic. My ultimate goal is to ulog syn packets for connection accounting.
I tried to place rules in PREROUTING chain, unsuccessfully.
Can iptable capture packets not sent to the local machine? If no, is there a way to do this?
Which table do you use for monitoring?
What you want to do is to use the filter table (the default one) and the FORWARDING chain: it is specifically designed to capture packets which "traverse" the machine. For instance:
iptables -A FORWARDING -p tcp --dport 80 -j LOG
The INPUT chain will capture packets from the outside destined to the local machine, and the OUTPUT chain will capture packets originating from the machine and going outside.
One side note: packets transiting through loopback go through both INPUT and OUTPUT chains.
As to PREROUTING, it is a chain meant to modify packets, if necessary, before the routing decision -- this is why, for instance, port redirection is done in there. And this is why the filter table has no hook in it: it does not make sense.
iptables will only work with IP packets somehow directed at your machine. So what you are trying to achieve will not be doable with iptables. For it to work would require that you set up your accounting machine as a router for all IP traffic.
What’s wrong with tcpdump for this task?
tcpdump -G 3600 -w tcpsyn-%FT%T.pcap tcp and 'tcp[tcpflags] & (tcp-ack|tcp-syn) = tcp-syn'
If you want all TCP initiation attempts.
tcpdump -G 3600 -w tcpsynack-%FT%T.pcap tcp and 'tcp[tcpflags] & (tcp-ack|tcp-syn) = (tcp-ack|tcp-syn)'
If you want all TCP sessions actually established.

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).