tproxy

package module
v0.0.0-...-9f75cc8 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 24, 2021 License: MIT Imports: 9 Imported by: 0

README

Golang TProxy GoDoc Go Report Card

Golang TProxy provides an easy to use wrapper for the Linux Transparent Proxy functionality.

Transparent Proxy (TProxy for short) provides the ability to transparently proxy traffic through a userland program without the need for conntrack overhead caused by using NAT to force the traffic into the proxy.

Another feature of TProxy is the ability to connect to remote hosts using the same client information as the original client making the connection. For example, if the connection 10.0.0.1:50073 -> 8.8.8.8:80 was intercepted, the service could make a connection to 8.8.8.8:80 pretending to come from 10.0.0.1:50073.

The linux kernel and IPTables handle diverting the packets back into the proxy for those remote connections by matching incoming packets to any locally bound sockets with the same details.

This is done in three steps. (Please note, this is from my understanding of how it works, which may be wrong in some places, so please correct me if I have described something wrong)

Step 1 - Binding a listener socket with the IP_TRANSPARENT socket option

Preparing a socket to receive connections with TProxy is really no different than what is normally done when setting up a socket to listen for connections. The only difference in the process is before the socket is bound, the IP_TRANSPARENT socket option.

syscall.SetsockoptInt(fileDescriptor, syscall.SOL_IP, syscall.IP_TRANSPARENT, 1)
Step 2 - Setting the IP_TRANSPARENT socket option on outbound connections

Same goes for making connections to a remote host pretending to be the client, the IP_TRANSPARENT socket option is set and the Linux kernel will allow the bind so along as a connection was intercepted with those details being used for the bind

Step 3 - Adding IPTables and routing rules to redirect traffic in both directions

Finally IPTables and routing rules need to be setup to tell Linux to redirect the desired traffic to the proxy application.

First make a new chain in the mangle table called DIVERT and add a rule to direct any TCP traffic with a matching local socket to the DIVERT chain

iptables -t mangle -N DIVERT
iptables -t mangle -A PREROUTING -p tcp -m socket -j DIVERT

Then in the DIVERT chain add rules to add routing mark of 1 to packets in the DIVERT chain and accept the packets

iptables -t mangle -A DIVERT -j MARK --set-mark 1
iptables -t mangle -A DIVERT -j ACCEPT

And add routing rules to direct traffic with mark 1 to the local loopback device so the Linux kernal can pipe the traffic into the existing socket.

ip rule add fwmark 1 lookup 100
ip route add local 0.0.0.0/0 dev lo table 100

Finally add a IPTables rule to catch new traffic on any desired port and send it to the TProxy server

iptables -t mangle -A PREROUTING -p tcp --dport 80 -j TPROXY --tproxy-mark 0x1/0x1 --on-port 8080

To test this out and see it work, try running the example in example/tproxy_example.go on a virtual machine and route some traffic through it.

Contributing

To contribute to this project, please follow this guide:

  1. Create an issue detailing your planned contribution
  2. Fork this repository and implement your contribution
  3. Create a pull request linking back to the issue
  4. Await approval and merging

TODOs

[x] Add support for proxying UDP connections

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func DialTCP

func DialTCP(laddr, raddr *net.TCPAddr) (*net.TCPConn, error)

DialTCP will open a TCP connection to the specified destination with the specified local address.

func DialTCPWithDevice

func DialTCPWithDevice(device string, laddr, raddr *net.TCPAddr) (*net.TCPConn, error)

DialTCPWithDevice will open a TCP connection to the specified destination with the specified local address, and will bind with interface `device`.

func DialUDP

func DialUDP(network string, laddr *net.UDPAddr, raddr *net.UDPAddr) (*net.UDPConn, error)

DialUDP connects to the remote address raddr on the network net, which must be "udp", "udp4", or "udp6". If laddr is not nil, it is used as the local address for the connection.

func ListenTCP

func ListenTCP(network string, laddr *net.TCPAddr) (net.Listener, error)

ListenTCP will construct a new TCP listener socket with the Linux IP_TRANSPARENT option set on the underlying socket

func ListenTCPWithDevice

func ListenTCPWithDevice(device, network string, laddr *net.TCPAddr) (net.Listener, error)

ListenTCPWithDevice construsts a new TCP listener socket with IP_TRANSPARENT option and binds with interface `device`.

func ListenUDP

func ListenUDP(network string, laddr *net.UDPAddr) (*net.UDPConn, error)

ListenUDP will construct a new UDP listener socket with the Linux IP_TRANSPARENT option set on the underlying socket

func ReadFromUDP

func ReadFromUDP(conn *net.UDPConn, b []byte) (int, *net.UDPAddr, *net.UDPAddr, error)

ReadFromUDP reads a UDP packet from c, copying the payload into b. It returns the number of bytes copied into b and the return address that was on the packet.

Out-of-band data is also read in so that the original destination address can be identified and parsed.

Types

type Conn

type Conn struct {
	*net.TCPConn
}

Conn describes a connection accepted by the TProxy listener.

It is simply a TCP connection with the ability to dial a connection to the original destination while assuming the IP address of the client

func (*Conn) DialOriginalDestination

func (conn *Conn) DialOriginalDestination(dontAssumeRemote bool) (*net.TCPConn, error)

DialOriginalDestination will open a TCP connection to the original destination that the client was trying to connect to before being intercepted.

When `dontAssumeRemote` is false, the connection will originate from the IP address and port that the client used when making the connection. Otherwise, when true, the connection will originate from an IP address and port assigned by the Linux kernel that is owned by the operating system

func (*Conn) DialOriginalDestinationWithDevice

func (conn *Conn) DialOriginalDestinationWithDevice(device string, dontAssumeRemote bool) (*net.TCPConn, error)

DialOriginalDestinationWithDevice will open a TCP connection to the original destination that the client was trying to connect to before being intercepted.

When `dontAssumeRemote` is false, the connection will originate from the IP address and port that the client used when making the connection. Otherwise, when true, the connection will originate from an IP address and port assigned by the Linux kernel that is owned by the operating system

type Listener

type Listener struct {
	// contains filtered or unexported fields
}

Listener describes a TCP Listener with the Linux IP_TRANSPARENT option defined on the listening socket

func (*Listener) Accept

func (listener *Listener) Accept() (net.Conn, error)

Accept waits for and returns the next connection to the listener.

This command wraps the AcceptTProxy method of the Listener

func (*Listener) AcceptTProxy

func (listener *Listener) AcceptTProxy() (*Conn, error)

AcceptTProxy will accept a TCP connection and wrap it to a TProxy connection to provide TProxy functionality

func (*Listener) Addr

func (listener *Listener) Addr() net.Addr

Addr returns the network address the listener is accepting connections from

func (*Listener) Close

func (listener *Listener) Close() error

Close will close the listener from accepting any more connections. Any blocked connections will unblock and close

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL