wangyu- / udp2raw

A Tunnel which Turns UDP Traffic into Encrypted UDP/FakeTCP/ICMP Traffic by using Raw Socket,helps you Bypass UDP FireWalls(or Unstable UDP Environment)
MIT License
7.27k stars 1.17k forks source link

Port sharing #131

Open JuniorJPDJ opened 6 years ago

JuniorJPDJ commented 6 years ago

I want to sugest you to make possible, to reuse port. Eg. Having http server at the same port as udp2raw in tcp mode. Something similar to that sslh is providing.

wangyu- commented 6 years ago

Added to Contribution Guide.

Someone suggested similiar idea on twitter before. I had some thought about it.

Seems like it will be much more complicated to implement than sslh, bc in this way you are trying to multiplex a port for both tcp socket and raw socket.

JuniorJPDJ commented 6 years ago

But you don't have to permit second app to listen at your port, you can just forward "not yours" packets to another port. It's much more simple solution, and IMO satisfying if fast enough

wangyu- commented 6 years ago

But you don't have to permit second app to listen at your port, you can just forward "not yours" packets to another port.

Agree. It's still not very easy, though.

Assume udp2raw is listening at 0.0.0.0:9966, ssh is running at 127.0.0.1:22. The socket listening on 9966 is a raw socket, you dont have tcp stack on 9966.

Forwarding 9966(raw) to 127.0.0.1:22(tcp), this can be done in two ways:

A. implement a tcp stack at 0.0.0.0:9966 , connect to 127.0.0.1:22 with a normal tcp socket, forward packets at tcp level. (implementing a tcp stack is obvious too complicated, so lets look at B)

B. do not implement a tcp stack at 0.0.0.0:9966, connect to 127.0.0.1:22 with another raw socket. Forward packets at ip level.

assume the 4-tuple of a packet received at 0.0.0.0:9966 is (client_ip,4567,server_ip,9966), to forward this packet to 127.0.0.1:22 you have to change the 4-tuple to (127.0.0.1,some_new_port,127.0.0.1,22). When you get a packet back from 127.0.0.1:22, you also have to do similiar things.

So, in this way, you essentially need to implement a SNAT and DNAT mechanism in user space with raw socket.

JuniorJPDJ commented 6 years ago

Yes, I missed it a bit. First thing that comes to my mind is marking verified our packets for netfilter instead of dropping everything. It will allow us not to implement TCP stack ourselves and out packets will not interfere with normal. But I don't really know if we can implement it in userspace.

JuniorJPDJ commented 6 years ago

I did a bit of research. I think it's already possible to set up without using any additional code in udp2raw (if you already have option to not process unknown packets) We can mark packets to DNAT when one of interesting us layer7 protocols detected with http://l7-filter.sourceforge.net/protocols

wangyu- commented 6 years ago

First thing that comes to my mind is marking verified our packets for netfilter instead of dropping everything.

Thats indeed a good idea.

if you already have option to not process unknown packets

udp2raw verifies packets with aes and md5, unknown packets will simply be ignored.

We can mark packets to DNAT when one of interesting us layer7 protocols detected with http://l7-filter.sourceforge.net/protocols

You can have a try. If this works, seems like llsh's function can also be implemented in this way.

Another interesting tool is iptables' bpf rule:

https://blog.cloudflare.com/bpf-the-forgotten-bytecode/ ,looks like its more flexible.

JuniorJPDJ commented 6 years ago

My idea with marking udp2raw packets is not good, every change in protocol will need to create new filtering rule + if udp2raw will ever become indistinguishable from ssl it will be.. impossible?

What if you put packets incomming for your port to NFQUEUE, process in udp2raw and pass if it's not udp2raw's packet? You will not even need raw socket 🤣

wangyu- commented 6 years ago

if udp2raw will ever become indistinguishable from ssl it will be.. impossible?

That wont be a problem, the first few packets of SSL handshake are actually in plaintext.

What if you put packets incomming for your port to NFQUEUE, process in udp2raw and pass if it's not udp2raw's packet?

Looks like another interesting solution. The advantage is, as you said, no new filtering rule is need for new protocols. The deficiency is, a new dependency "libnetfilter_queue" has to be involved.

You will not even need raw socket

I think a raw socket is still needed for sending ?

JuniorJPDJ commented 6 years ago

The deficiency is, a new dependency "libnetfilter_queue" has to be involved.

You can make it optional :D

I think a raw socket is still needed for sending ?

Yes, I think I missed that