iptables port forwarding in the ohter direction - linux

I use linux router for accessing internet via PPPoE. This box has two interfaces: eth0 for internal LAN and eth1 for establish a ppp0-interface on a PPPoE-Modem. For firewalling and port forwarding I use iptables with nat.
This works as expecting: I can go in the internet from the LAN, I can access certain service in the LAN from outside by port forwarding:
iptables -t nat -A PREROUTING -p tcp --dport 9999 -DNAT --to 192.168.2.10:22
(as an example for accessing the ssh-port of a certain machine inside my LAN from outside)
But I want to access a single machine (192.168.8.2) on the WAN-Port eth1 from inside of the LAN:
for this reason, the eth1 is configured as:
ip addr add 192.168.8.1 dev eth1
So I can ssh 192.168.8.2 from the console on the router. This works as expected. but I want to access this also from machines from the LAN.
iptables -t nat -A PREROUTING -p tcp --dport 9997 -DNAT --to 192.168.8.2:22
but this isnt going to work. I see packets coming from my LAN-side-machine going in on eth0 and addressing 192.168.8.2, but I dont get an answer.
can someone point me to, where my error is?
thanks in advance
Marco

Unless the server (192.168.8.2) knows how to get back to the computers on the LAN (would have to check routing for traffic coming back from that server), you would have to add a -t nat POSTROUTING rule on the router to make it look like it's traffic that's going out from the router (which I would guess is already accessible from 192.168.8.2). The the traffic would be able to get back to the router when the server is responding and the router would take care of unNATing it.

Related

How to block the connection to an IP which is created in docker container on host

There is a docker container running in bridge network mode. Inside the container, it creates a connection to, say, 10.123.123.1:6666. I'd like to block this connection on host through IPTABLES, something like sudo iptables -I OUTPUT -p tcp -d 10.123.123.1 -j DROP, but it doesn't work. Could anyone help me on this please?
I can't even see this connection on host by command netstat -an, but I can see it inside the container.
I don't have to use IPTABLES, but I can't change the configuration of the docker running.
These packets are going through INPUT & OUTPUT chains in the container's network namespace, and not in the host's network namespace.
All your host network namespace does is forward these packets so you need to alter the FORWARD chain with a rule similar to iptables -I FORWARD -p tcp -d 10.123.123.1 -j DROP. Bear in mind that Docker alters iptables rules which may punch holes in the firewall.

How to restrict access from internet to containers ports on remote linux server?

I use docker-compose on ubuntu 18 on remote server.
How, with iptables, can i block access from the internet to the docker port and only allow access to it from the localhost of this server?
For instance, i want to block 4150 port for internet. Trying this:
iptables -A DOCKER-USER -p tcp --dport 4150 -j DROP does not block the port - still can access to it from the internet (not from server machine).
How can i block access from internet to all ports that are on the server, but allow only 22,80 ? And keep that ports available from localhost of the server (eg from the server itself) ?
Not the IPTables based solution you're looking for, but a much simpler solution is to only publish to a specific interface, instead of all interfaces. And when that interface is the loopback interface, e.g. 127.0.0.1, you'll only be able to access the port locally. To do this, add the interface to the beginning of the publish spec:
docker run -p 127.0.0.1:4150:4150 ...
Or a similar syntax in the compose file:
...
ports:
- 127.0.0.1:4150:4150
...
As for why the command you tried using didn't work, this needs conntrack to get the original port rather than the docker mapped port:
iptables -I DOCKER-USER -p tcp -m contrack --ctorigdstport 4150 -j DROP
This also changed from -A (append) to -I (insert) because there's a default rule to accept everything in that list.

How to access Weave DNS-Server from external?

I use the Weave network plugin on a Docker-Swarm.
I created a docker network with a specific IP-Range, different from the default Weave Network, to which I route from my internal network.
To make the containers even better accessible I use weave to attach DNS names like containername.auto.mycompany.de. Now I want to access those from my company Network. The Problem is, that weave only allows access to the weave DNS from the local host.
Like on one of my swarm nodes i can do:
host foobar.auto.mycompany.de 172.17.0.1
Using domain server:
Name: 172.17.0.1
Address: 172.17.0.1#53
Aliases:
foobar.auto.mycompany.de has address 10.40.13.3
Host foobar.auto.mycompany.de not found: 3(NXDOMAIN)
Host foobar.auto.mycompany.de not found: 3(NXDOMAIN)
But I don't find a way to make the weave container accessible on one of the IP's from this (10.40.130/24) docker network or expose the port to the swarm node.
The only way I can think of, but don't like, is doing something like this:
iptables -t nat -A DOCKER -p tcp --dport 53 -j DNAT --to-destination 172.17.0.1:53
(this does not work, it's just the idea)
Or tamper with the weave script to make it expose the port on start of the weave container.
Does anybody know of a better solution?
In fact setting the rules
iptables -A DOCKER -p tcp -m tcp --dport 53 -j DNAT --to-destination 172.17.0.1:53
iptables -A DOCKER -p udp -m udp --dport 53 -j DNAT --to-destination 172.17.0.1:53
does it. When I first tried that, I simply missed to see, that my request would have come from "outside" the server to work, not from inside to the loopback device.
Still not a pretty solution but it does the job. I'm looking forward to see better solutions from you guys.
(Bounty stands!)

Listening to EVERY port on a machine

For testing purposes I want to build a server that listens for TCP connections to every port (or at least on most of the ports) on a certain interface (e.g., eth0). The server is accessed via SSH to eth1, so no problem there. (I do not care about UDP or other protocols)
I want to do a special kind of middlebox detection/analysis, therefore I need to be able to fully establish a connection. Having an HTTP connection would be the best, because the "client" could be implemented as JS in the Browser.
I started with a simple jetty server, but had to realize that jetty needs to spawn at least on thread per port it is listening to. This leads to problems when I want to listen to several thousand ports. Or is there a way around that?
My next try was to use iptables:
sudo iptables -t nat -A PREROUTING -i eth0 -p tcp -j DNAT --to-destination 127.0.0.1:8080`
It seemed to work. It allows to connect on every port and the traffic gets routed to the local port 8080 where jetty listens. But now I no longer know which port was used by the client. Because jetty thinks the connection was established via port 8080. Is there a way to determine the real incomming port from jetty? I could send the port as part of the HTTP request, but if the client tries to contact port 1234 .. and a middlebox redirects this to port 5678 .. I am unable to know what port was used.
I also tried userland solutions like socat. The problem was even worse than before. Because now jetty also saw the remote IP as being 127.0.0.1.
Or, is there another way to achieve this?
Oh and btw: I have full control of the machine. So I could change the kernel or whatever is needed. Right now I use Ubuntu 14.04 LTS, but if a solution needs something else I could go with that.
NB: This is a Python solution, because I know Python, but you can accomplish the same thing in any language the exposes the underlying C library getsockopt call.
If you replace your DNAT rule with a REDIRECT rule, you can then
use getsockopt with the SO_ORIGINAL_DST option to retrieve the
original address of a REDIRECT-ed connection.
Consider the following code:
#!/usr/bin/python
import socket
import struct
SO_ORIGINAL_DST = 80
s = socket.socket()
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(('0.0.0.0', 2000))
s.listen(10)
while True:
csock, caddr = s.accept()
orig_dst = csock.getsockopt(socket.SOL_IP, SO_ORIGINAL_DST, 16)
orig_port = struct.unpack('>H', orig_dst[2:4])
orig_addr = socket.inet_ntoa(orig_dst[4:8])
print 'connection from', caddr
print 'connection to', (orig_addr, orig_port)
print
If I have an iptables rule that looks like:
# iptables -t nat -A PREROUTING -p tcp --dport 1500:1600 \
-j REDIRECT --to-port 2000
And while the above Python code is running I connect from another
host to my_ip_address:1500, I see:
connection from ('192.168.1.20', 35790)
connection to ('192.168.1.75', (1500,))
And if I connect to port 1550 I see:
connection from ('192.168.1.20', 42054)
connection to ('192.168.1.75', (1550,))
Which I think is exactly what you were asking for. Note that to my knowledge this will only work for TCP connections; there are other solutions (possibly involving the TPROXY iptables target) that may work with UDP connections as well.

Cannot connect to google compute engine virtual machine by vnc

I have created a debian wheezy virtual machine in google compute engine but I am unable to connect to it with vnc.
Here is what I have done
Installed gnome and the rebooted the VM
install tightvncserver and started it
I have tried to connect using the static ip that I've attached to the VM but I'm getting the error: "the connection was refused by the host computer".
I thought it was the firewall that was the issue so I disabled iptable using the following commands
$ sudo iptables-save > /root/firewall.rules
iptables -F
iptables -X
iptables -t nat -F
iptables -t nat -X
iptables -t mangle -F
iptables -t mangle -X
iptables -P INPUT ACCEPT
iptables -P OUTPUT ACCEPT
iptables -P FORWARD ACCEPT
and I have created rules in google firewall to allow ports 0-65535 for tcp and udp but it still does not work.
Anyone knows how to do it?
Thanks in advance
By default, all incoming traffic from outside a network is blocked and no packet is allowed into an instance without an appropriate firewall rule. To allow incoming network traffic, you need to set up firewall rules to permit these connections:
start the VNC service
look at VNC server settings or netstat -nap to find out the listening port of vnc server
under Google Developer console -> Compute Engine -> Networks -> default -> Firewall rules
create a new rule and open appropriate ports for incoming vnc connections.
VNC uses by default port 5901. In the 'VNC server' field, specify the ip address and the port 5901.
Example: VNC ***Server: 123.123.123.123:5901
Encryption: let VNC Server choose***
Be aware that the free edition of VNC doesn't support encryption, it only encrypts your user name and password. One thing also to configure is /etc/sysconfig/vncservers file where you have to specify the user and the port that VNC server should listen to, and make sure it's not commented
Example:
VNCSERVERS="1:USERNAME"
VNCSERVERAR0GS[1]="-geometry 800x600 -listen tcp -5901"

Resources