1

I'm trying to setup a transparent proxy across network namespaces.

First I create the network namespaces, virtual ethernet devices and enable forwarding inside one of the namespaces:

ip netns add nsx
ip netns add nsy
ip link add vethx type veth peer name peerx netns nsx
ip link set vethx up
ip address add 10.0.0.1/24 dev vethx
ip netns exec nsx ip link set peerx up
ip netns exec nsx ip address add 10.0.0.2/24 dev peerx
ip netns exec nsx ip link add vethy type veth peer name peery netns nsy
ip netns exec nsx ip link set vethy up
ip netns exec nsx ip address add 10.0.1.1/24 dev vethy
ip netns exec nsx sysctl -w net.ipv4.conf.peerx.forwarding=1
ip netns exec nsx sysctl -w net.ipv4.conf.vethy.forwarding=1
ip netns exec nsy ip link set peery up
ip netns exec nsy ip address add 10.0.1.2/24 dev peery
ip netns exec nsy ip route add default via 10.0.1.1 dev peery

And I set up some iptables rules to forward the traffic inside the namespace "nsx":

ip netns exec nsx iptables -t nat -A PREROUTING -i vethy -p tcp --syn -j DNAT --to-destination 10.0.0.1:19040
ip netns exec nsx iptables -t nat -A POSTROUTING -p tcp -s 10.0.1.2 -d 10.0.0.1 --dport 19040 -j SNAT --to-source 10.0.0.2
ip netns exec nsx iptables -I FORWARD -o peerx -i vethy -p tcp -s 10.0.1.2 -d 10.0.0.1 --dport 19040 -j ACCEPT
ip netns exec nsx iptables -I FORWARD -i peerx -o vethy -m state --state ESTABLISHED,RELATED,NEW -d 10.0.1.2 -s 10.0.0.1 -j ACCEPT

When I try to curl some IP I get the following error:

$ ip netns exec nsy curl 1.1.1.1
curl: (56) Recv failure: Connection reset by peer

I tested with different transparent forwarders and I see error messages such as:

2022/07/18 15:27:18 redir_linux.go:89: [redir] failed to get target address: no such file or directory

2022-07-18 15:28:49 INF: [tcp_tproxy_accept_cb] source socket address: 10.0.0.2#33830
2022-07-18 15:28:49 ERR: [get_tcp_orig_dstaddr] getsockopt(5, SO_ORIGINAL_DST): No such file or directory

Tor shows this message:

Jul 18 15:26:17.000 [debug] connection_handle_listener_read(): Connection accepted on socket 8 (child of fd 6).
Jul 18 15:26:17.000 [info] connection_handle_listener_read(): New SOCKS connection opened from 10.0.0.2.
Jul 18 15:26:17.000 [debug] connection_add_impl(): new conn type Socks, socket 8, address 10.0.0.2, n_conns 4.
Jul 18 15:26:17.000 [debug] connection_ap_process_transparent(): entered.
Jul 18 15:26:17.000 [warn] getsockopt() failed: No such file or directory
Jul 18 15:26:17.000 [warn] Fetching original destination failed. Closing.
Jul 18 15:26:17.000 [debug] conn_close_if_marked(): Cleaning up connection (fd 8).
Jul 18 15:26:17.000 [debug] connection_remove(): removing socket 8 (type Socks), n_conns now 4
Jul 18 15:26:17.000 [debug] connection_free_minimal(): closing fd 8.

=============================

What can be done to solve this problem? Should I add a special rule in the scheme to make it work?

=============================

UPDATE:

I used this rule on host side:

iptables -t nat -A PREROUTING -i vethx -p tcp -j DNAT --sport 19040 -s 10.0.0.0/24 -d 10.0.1.0/24 --to-destination 10.0.1.1

The connection goes via transparent proxy to a SOCK5 proxy in the host side, by the address received by SOCKS5 proxy is 10.0.0.1 (local).

What can I do to make the connection made inside network namespace "nsy" reach SOCKS5 server with the right IP?

phantomcraft
  • 133
  • 5

1 Answers1

1

Assuming an application expect a SOCKS proxy which for whatever reason, must live inside a network namespace (eg, to benefit from a namespace OpenVPN connection), then the following will make it work

  1. Assume a working (possibly openvpn-enabled) network namespace, named "protected"

$ ip netns add protected

  1. Assume the network namespace is up and running (add your own sudo sauce if necessary)

$ ip netns exec protected <command>

  1. Execute a SOCKS proxy server within the namespace (here using microsocks)

$ ip netns exec protected microsocks -p 1234

  1. Setup a bridge between a (shared) unix socket and the (namespaced) SOCKS proxy

$ ip netns exec protected socat unix-listen:/tmp/foo.sock,reuseaddr,fork tcp4:127.0.0.1:1234

  1. Forward all TCP (including SOCKS connection attempts) from the host (on a given port) to the unix socket

$ socat tcp-l:9060,fork,reuseaddr /tmp/foo.sock

  1. Connect the application to the (non-namespaced but forwarded) TCP port localhost:9060
drzraf
  • 121
  • 3