fatedier / frp

A fast reverse proxy to help you expose a local server behind a NAT or firewall to the internet.
Apache License 2.0
85.59k stars 13.26k forks source link

UDP Packets over 1500 bytes are clipped #3786

Closed half2me closed 11 months ago

half2me commented 11 months ago

Bug Description

When proxying UDP packets over 1500 bytes, only the first 1500 bytes of the payload are received, the rest is lost. This behaviour seems to be the same regardless of the protocol used to connect to frps. I've tried tcp, quic and kcp, they all produce the same result.

frpc Version

0.52.3

frps Version

0.52.3

System Architecture

server: linux_arm64, client: darwin_arm64

Configurations

Server:

bindPort = 7000
quicBindPort = 7000
vhostHTTPPort = 80
vhostHTTPSPort = 443

webserver.port = 8080
webserver.user = "admin"
webserver.pwd = "redacted"

auth.method = "token"
auth.token = "redacted"

Client:

[common]
server_addr = redacted
server_port = 7000
protocol = tcp # also tried kcp and quic
token = redacted

[sip-udp]
type = udp
local_ip = 127.0.0.1
local_port = 5060
remote_port = 5060

Logs

No response

Steps to reproduce

  1. Start a sample python UDP server:
    
    import socket

bufferSize = 65535 UDPServerSocket = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM) UDPServerSocket.bind(("127.0.0.1", 5060))

while True: bytesAddressPair = UDPServerSocket.recvfrom(bufferSize) print("Got {} bytes from client".format(len(bytesAddressPair[0])))


2. Send a large UDP packet directly (without the proxy)
```python
import socket

# addressing information of target
IPADDR = "127.0.0.1"
PORTNUM = 5060

payload = "A" * 5000
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, 0)
s.connect((IPADDR, PORTNUM))
res = s.send(payload.encode())
print("Sent {0} bytes".format(res))
s.close()

The server console should show: Got 5000 bytes from client

  1. Now send the same UDP packet over frp. Start frpc, and rerun the script, but change the IPADDR from 127.0.0.1 to the public IP where frps is listening.

  2. The console of the python server now shows: Got 1500 bytes from client This is the wrong size, as its only the first part of the packet.

Affected area

half2me commented 11 months ago

I've tried to send 1501 bytes of payload, and that fails the same. It seems like 1500 is the hard limit for UDP payload.

half2me commented 11 months ago

Update, I've found the UDPPacketSize parameter that is configurable. If I increase this, it works. Maybe this could be added to the documentation?

xqzr commented 11 months ago

Update, I've found the UDPPacketSize parameter that is configurable. If I increase this, it works. Maybe this could be added to the documentation?

https://gofrp.org/zh-cn/docs/reference/client-configures/#clientcommonconfig

fatedier commented 11 months ago

https://github.com/fatedier/frp#configuration-files

@half2me It is difficult for us to describe the configuration of all functions one by one. Here, it is mentioned that you can find more capabilities in the full example configuration that are not mentioned in the documentation.

half2me commented 11 months ago

@fatedier Yes, I understand. But I spent at least a few hours debugging this issue yesterday thinking it was something wrong in my application. I didn't expect frp to be modifying my data as a "default" behaviour. Is there any reason that the max udp packet size is set to 1500 instead of a higher value? What is the purpose of limiting it? Is it for memory saving?

xqzr commented 11 months ago

@fatedier Yes, I understand. But I spent at least a few hours debugging this issue yesterday thinking it was something wrong in my application. I didn't expect frp to be modifying my data as a "default" behaviour. Is there any reason that the max udp packet size is set to 1500 instead of a higher value? What is the purpose of limiting it? Is it for memory saving?

1500 是标准的 以太网 MTU 值