[GH-ISSUE #5289] UDP On the server for frp is not forwarding fully. #4083

Closed
opened 2026-05-05 14:35:04 -06:00 by gitea-mirror · 7 comments
Owner

Originally created by @liam6080 on GitHub (Apr 15, 2026).
Original GitHub issue: https://github.com/fatedier/frp/issues/5289

Bug Description

It is in regards to the server calling on: *:19132 and *:30004 yet it can not be accessed via the public IP.

I can not see any way to set the server to fully listen on the public IP's and it does not work via the host IP's as expected.

So the main thing is, It works from client to the server, Yet the server is not pushing out the ports public & This is causing issues for things like: bedrock and simple voice chat on Minecraft.

frpc Version

0.68.0

frps Version

0.68.0

System Architecture

ubuntu/amd64

Configurations

Proxy/Server 1:

bindPort = 7000

# Specify a UDP port for KCP.
kcpBindPort = 7000

# Optional dashboard
webServer.addr = "0.0.0.0"
webServer.port = 7500
webServer.user = "admin"
webServer.password = "PASSWORD"

# IMPORTANT for UDP + MC traffic
transport.maxPoolCount = 5000
udpPacketSize = 1500

# Optional: Restrict allowed ports
allowPorts = [
  { single = 30004 },
  { single = 30100 },
  { single = 19131 },
  { single = 19132 }
]

# Optional security
auth.method = "token"
auth.token = "TOKEN"

Proxy/Server 2:

bindPort = 7000

# Specify a UDP port for KCP.
kcpBindPort = 7000

# Optional dashboard
webServer.addr = "0.0.0.0"
webServer.port = 7500
webServer.user = "admin"
webServer.password = "PASSWORD"

# IMPORTANT for UDP + MC traffic
transport.maxPoolCount = 5000
udpPacketSize = 1500

# Optional: Restrict allowed ports
allowPorts = [
  { single = 30004 },
  { single = 30100 },
  { single = 19131 },
  { single = 19132 }
]

# Optional security
auth.method = "token"
auth.token = "TOKEN"

Client configs:

serverAddr = "XXX.XXX.XXX.171" #Other config has .172
# Same as the 'kcpBindPort' in frps.toml
serverPort = 7000
#enableUdp = true

auth.method = "token"
auth.token = "TOKEN"

#[transport]

#poolCount = 5
transport.protocol = "kcp"

[[proxies]]

name = "minecraft-bedrock"
type = "udp"
localIP = "172.18.0.1"
localPort = 19132
remotePort = 19132

# now v1 and v2 are supported
transport.proxyProtocolVersion = "v2"

[[proxies]]

name = "voice-chat"
type = "udp"
localIP = "127.18.0.1"
localPort = 30004
remotePort = 30004

# now v1 and v2 are supported
#transport.proxyProtocolVersion = "v2"

#name = "test-tcp"
#type = "tcp"
#localIP = "127.0.0.1"
#localPort = 22
#remotePort = 6000

Logs

No response

Steps to reproduce

  1. I don't know how to, There is no way to.
    ...

Affected area

  • Docs
  • Installation
  • Performance and Scalability
  • Security
  • User Experience
  • Test and Release
  • Developer Infrastructure
  • Client Plugin
  • Server Plugin
  • Extensions
  • Others
Originally created by @liam6080 on GitHub (Apr 15, 2026). Original GitHub issue: https://github.com/fatedier/frp/issues/5289 ### Bug Description It is in regards to the server calling on: *:19132 and *:30004 yet it can not be accessed via the public IP. I can not see any way to set the server to fully listen on the public IP's and it does not work via the host IP's as expected. So the main thing is, It works from client to the server, Yet the server is not pushing out the ports public & This is causing issues for things like: bedrock and simple voice chat on Minecraft. ### frpc Version 0.68.0 ### frps Version 0.68.0 ### System Architecture ubuntu/amd64 ### Configurations Proxy/Server 1: ``` bindPort = 7000 # Specify a UDP port for KCP. kcpBindPort = 7000 # Optional dashboard webServer.addr = "0.0.0.0" webServer.port = 7500 webServer.user = "admin" webServer.password = "PASSWORD" # IMPORTANT for UDP + MC traffic transport.maxPoolCount = 5000 udpPacketSize = 1500 # Optional: Restrict allowed ports allowPorts = [ { single = 30004 }, { single = 30100 }, { single = 19131 }, { single = 19132 } ] # Optional security auth.method = "token" auth.token = "TOKEN" ``` Proxy/Server 2: ``` bindPort = 7000 # Specify a UDP port for KCP. kcpBindPort = 7000 # Optional dashboard webServer.addr = "0.0.0.0" webServer.port = 7500 webServer.user = "admin" webServer.password = "PASSWORD" # IMPORTANT for UDP + MC traffic transport.maxPoolCount = 5000 udpPacketSize = 1500 # Optional: Restrict allowed ports allowPorts = [ { single = 30004 }, { single = 30100 }, { single = 19131 }, { single = 19132 } ] # Optional security auth.method = "token" auth.token = "TOKEN" ``` Client configs: ``` serverAddr = "XXX.XXX.XXX.171" #Other config has .172 # Same as the 'kcpBindPort' in frps.toml serverPort = 7000 #enableUdp = true auth.method = "token" auth.token = "TOKEN" #[transport] #poolCount = 5 transport.protocol = "kcp" [[proxies]] name = "minecraft-bedrock" type = "udp" localIP = "172.18.0.1" localPort = 19132 remotePort = 19132 # now v1 and v2 are supported transport.proxyProtocolVersion = "v2" [[proxies]] name = "voice-chat" type = "udp" localIP = "127.18.0.1" localPort = 30004 remotePort = 30004 # now v1 and v2 are supported #transport.proxyProtocolVersion = "v2" #name = "test-tcp" #type = "tcp" #localIP = "127.0.0.1" #localPort = 22 #remotePort = 6000 ``` ### Logs _No response_ ### Steps to reproduce 1. I don't know how to, There is no way to. ... ### Affected area - [ ] Docs - [ ] Installation - [ ] Performance and Scalability - [ ] Security - [ ] User Experience - [ ] Test and Release - [ ] Developer Infrastructure - [ ] Client Plugin - [ ] Server Plugin - [ ] Extensions - [x] Others
gitea-mirror 2026-05-05 14:35:04 -06:00
Author
Owner

@fatedier commented on GitHub (Apr 15, 2026):

Hi @liam6080, a few things to check before this can be treated as a frp bug:

1. Typo in the voice-chat proxy:

localIP = "127.18.0.1"   # not a valid address — you probably meant 172.18.0.1

2. Remove transport.proxyProtocolVersion = "v2" from the Minecraft Bedrock UDP proxy. frpc prepends a PROXY v2 header to the first UDP packet, which corrupts the RakNet handshake because Bedrock servers don't understand PROXY protocol. Only use this when localPort is something that actually parses PROXY protocol.

3. "Not reachable via public IP" is almost always a firewall / security group issue, not frp. frps binds UDP on 0.0.0.0:<remotePort> by default. Please verify:

ss -ulnp | grep frps                 # on the server
nc -u <public-ip> 19132              # from outside

and confirm your cloud security group / ufw / iptables allows inbound UDP on 19132, 30004, 19131, 30100.

4. Please attach frps and frpc logs (the Logs section is empty) — without them we can't tell whether the proxy is even registered on the server.

Fix 1 & 2, then share the ss output and logs and we can go from there.

<!-- gh-comment-id:4248791541 --> @fatedier commented on GitHub (Apr 15, 2026): Hi @liam6080, a few things to check before this can be treated as a frp bug: **1. Typo in the voice-chat proxy:** ```toml localIP = "127.18.0.1" # not a valid address — you probably meant 172.18.0.1 ``` **2. Remove `transport.proxyProtocolVersion = "v2"` from the Minecraft Bedrock UDP proxy.** frpc prepends a PROXY v2 header to the first UDP packet, which corrupts the RakNet handshake because Bedrock servers don't understand PROXY protocol. Only use this when `localPort` is something that actually parses PROXY protocol. **3. "Not reachable via public IP" is almost always a firewall / security group issue, not frp.** frps binds UDP on `0.0.0.0:<remotePort>` by default. Please verify: ```bash ss -ulnp | grep frps # on the server nc -u <public-ip> 19132 # from outside ``` and confirm your cloud security group / `ufw` / `iptables` allows inbound UDP on 19132, 30004, 19131, 30100. **4. Please attach `frps` and `frpc` logs** (the `Logs` section is empty) — without them we can't tell whether the proxy is even registered on the server. Fix 1 & 2, then share the `ss` output and logs and we can go from there.
Author
Owner

@liam6080 commented on GitHub (Apr 15, 2026):

1: I fixed that IP address issue, Thank you!

2: I removed the proxy protocal.

3: Running on the server:

# ss -ulnp | grep frps 
UNCONN 0      0                  *:19132            *:*    users:(("frps",pid=11849,fd=8))          
UNCONN 0      0                  *:30004            *:*    users:(("frps",pid=11849,fd=9))          
UNCONN 0      0                  *:7000             *:*    users:(("frps",pid=11849,fd=7)) 

3.1: Running remote:

$ nc -u 62.72.177.172 19132

"No reply".

4: Here are the logs:

Client 1 for Proxy 1 stopped working even after copying the same config of client: "didn't edit anything and the port filters are the same on each server"

# ./frpc -c ./frpc.toml
2026-04-15 08:02:51.213 [I] [sub/root.go:201] start frpc service for config file [./frpc.toml] with aggregated configuration
2026-04-15 08:02:51.213 [I] [client/service.go:378] try to connect to server...
2026-04-15 08:03:01.214 [W] [client/service.go:381] connect to server error: connection write timeout
2026-04-15 08:03:01.214 [I] [sub/root.go:218] frpc service for config file [./frpc.toml] stopped
login to the server failed: connection write timeout. With loginFailExit enabled, no additional retries will be attempted

Proxy 1:

# ./frps -c ./frps.toml
2026-04-15 07:56:07.898 [I] [frps/root.go:115] frps uses config file: ./frps.toml
2026-04-15 07:56:07.997 [I] [server/service.go:246] frps tcp listen on 0.0.0.0:7000
2026-04-15 07:56:07.997 [I] [server/service.go:255] frps kcp listen on udp 0.0.0.0:7000
2026-04-15 07:56:07.997 [I] [frps/root.go:124] frps started successfully
2026-04-15 07:56:07.997 [I] [server/service.go:363] dashboard listen on 0.0.0.0:7500

Client 2 for Proxy 2:

# ./frpc -c ./frpc2.toml
2026-04-15 08:02:53.041 [I] [sub/root.go:201] start frpc service for config file [./frpc2.toml] with aggregated configuration
2026-04-15 08:02:53.041 [I] [client/service.go:378] try to connect to server...
2026-04-15 08:02:53.124 [I] [client/service.go:370] [af24351f3ac7e9ed] login to server success, get run id [af24351f3ac7e9ed]
2026-04-15 08:02:53.124 [I] [proxy/proxy_manager.go:180] [af24351f3ac7e9ed] proxy added: [minecraft-bedrock voice-chat]
2026-04-15 08:02:53.165 [I] [client/control.go:176] [af24351f3ac7e9ed] [voice-chat] start proxy success
2026-04-15 08:02:53.165 [I] [client/control.go:176] [af24351f3ac7e9ed] [minecraft-bedrock] start proxy success
2026-04-15 08:02:53.651 [I] [proxy/udp.go:90] [af24351f3ac7e9ed] [voice-chat] incoming a new work connection for udp proxy, 62.72.177.172:7000
2026-04-15 08:02:53.672 [I] [proxy/udp.go:90] [af24351f3ac7e9ed] [minecraft-bedrock] incoming a new work connection for udp proxy, 62.72.177.172:7000

Proxy 2:

# ./frps -c ./frps.toml
2026-04-15 08:02:41.698 [I] [frps/root.go:115] frps uses config file: ./frps.toml
2026-04-15 08:02:41.780 [I] [server/service.go:246] frps tcp listen on 0.0.0.0:7000
2026-04-15 08:02:41.780 [I] [server/service.go:255] frps kcp listen on udp 0.0.0.0:7000
2026-04-15 08:02:41.780 [I] [frps/root.go:124] frps started successfully
2026-04-15 08:02:41.780 [I] [server/service.go:363] dashboard listen on 0.0.0.0:7500
2026-04-15 08:02:53.105 [I] [server/service.go:595] [af24351f3ac7e9ed] client login info: ip [45.XXX.XXX.XXX:54231] version [0.68.0] hostname [9950x-100] os [linux] arch [amd64]
2026-04-15 08:02:53.146 [I] [proxy/udp.go:103] [af24351f3ac7e9ed] [voice-chat] udp proxy listen port [30004]
2026-04-15 08:02:53.146 [I] [server/control.go:392] [af24351f3ac7e9ed] new proxy [voice-chat] type [udp] success
2026-04-15 08:02:53.146 [I] [proxy/udp.go:103] [af24351f3ac7e9ed] [minecraft-bedrock] udp proxy listen port [19132]
2026-04-15 08:02:53.146 [I] [server/control.go:392] [af24351f3ac7e9ed] new proxy [minecraft-bedrock] type [udp] success

Also on top of that even with the working: 62.72.177.172 I can not connect to bedrock or simple voice chat as well.

<!-- gh-comment-id:4250309155 --> @liam6080 commented on GitHub (Apr 15, 2026): 1: I fixed that IP address issue, Thank you! 2: I removed the proxy protocal. 3: Running on the server: ``` # ss -ulnp | grep frps UNCONN 0 0 *:19132 *:* users:(("frps",pid=11849,fd=8)) UNCONN 0 0 *:30004 *:* users:(("frps",pid=11849,fd=9)) UNCONN 0 0 *:7000 *:* users:(("frps",pid=11849,fd=7)) ``` 3.1: Running remote: ``` $ nc -u 62.72.177.172 19132 ``` "No reply". 4: Here are the logs: Client 1 for Proxy 1 stopped working even after copying the same config of client: "didn't edit anything and the port filters are the same on each server" ``` # ./frpc -c ./frpc.toml 2026-04-15 08:02:51.213 [I] [sub/root.go:201] start frpc service for config file [./frpc.toml] with aggregated configuration 2026-04-15 08:02:51.213 [I] [client/service.go:378] try to connect to server... 2026-04-15 08:03:01.214 [W] [client/service.go:381] connect to server error: connection write timeout 2026-04-15 08:03:01.214 [I] [sub/root.go:218] frpc service for config file [./frpc.toml] stopped login to the server failed: connection write timeout. With loginFailExit enabled, no additional retries will be attempted ``` Proxy 1: ``` # ./frps -c ./frps.toml 2026-04-15 07:56:07.898 [I] [frps/root.go:115] frps uses config file: ./frps.toml 2026-04-15 07:56:07.997 [I] [server/service.go:246] frps tcp listen on 0.0.0.0:7000 2026-04-15 07:56:07.997 [I] [server/service.go:255] frps kcp listen on udp 0.0.0.0:7000 2026-04-15 07:56:07.997 [I] [frps/root.go:124] frps started successfully 2026-04-15 07:56:07.997 [I] [server/service.go:363] dashboard listen on 0.0.0.0:7500 ``` Client 2 for Proxy 2: ``` # ./frpc -c ./frpc2.toml 2026-04-15 08:02:53.041 [I] [sub/root.go:201] start frpc service for config file [./frpc2.toml] with aggregated configuration 2026-04-15 08:02:53.041 [I] [client/service.go:378] try to connect to server... 2026-04-15 08:02:53.124 [I] [client/service.go:370] [af24351f3ac7e9ed] login to server success, get run id [af24351f3ac7e9ed] 2026-04-15 08:02:53.124 [I] [proxy/proxy_manager.go:180] [af24351f3ac7e9ed] proxy added: [minecraft-bedrock voice-chat] 2026-04-15 08:02:53.165 [I] [client/control.go:176] [af24351f3ac7e9ed] [voice-chat] start proxy success 2026-04-15 08:02:53.165 [I] [client/control.go:176] [af24351f3ac7e9ed] [minecraft-bedrock] start proxy success 2026-04-15 08:02:53.651 [I] [proxy/udp.go:90] [af24351f3ac7e9ed] [voice-chat] incoming a new work connection for udp proxy, 62.72.177.172:7000 2026-04-15 08:02:53.672 [I] [proxy/udp.go:90] [af24351f3ac7e9ed] [minecraft-bedrock] incoming a new work connection for udp proxy, 62.72.177.172:7000 ``` Proxy 2: ``` # ./frps -c ./frps.toml 2026-04-15 08:02:41.698 [I] [frps/root.go:115] frps uses config file: ./frps.toml 2026-04-15 08:02:41.780 [I] [server/service.go:246] frps tcp listen on 0.0.0.0:7000 2026-04-15 08:02:41.780 [I] [server/service.go:255] frps kcp listen on udp 0.0.0.0:7000 2026-04-15 08:02:41.780 [I] [frps/root.go:124] frps started successfully 2026-04-15 08:02:41.780 [I] [server/service.go:363] dashboard listen on 0.0.0.0:7500 2026-04-15 08:02:53.105 [I] [server/service.go:595] [af24351f3ac7e9ed] client login info: ip [45.XXX.XXX.XXX:54231] version [0.68.0] hostname [9950x-100] os [linux] arch [amd64] 2026-04-15 08:02:53.146 [I] [proxy/udp.go:103] [af24351f3ac7e9ed] [voice-chat] udp proxy listen port [30004] 2026-04-15 08:02:53.146 [I] [server/control.go:392] [af24351f3ac7e9ed] new proxy [voice-chat] type [udp] success 2026-04-15 08:02:53.146 [I] [proxy/udp.go:103] [af24351f3ac7e9ed] [minecraft-bedrock] udp proxy listen port [19132] 2026-04-15 08:02:53.146 [I] [server/control.go:392] [af24351f3ac7e9ed] new proxy [minecraft-bedrock] type [udp] success ``` Also on top of that even with the working: 62.72.177.172 I can not connect to bedrock or simple voice chat as well.
Author
Owner

@fatedier commented on GitHub (Apr 15, 2026):

Thanks for the details. A few observations:

1. nc -u ... 19132 → "no reply" is not a valid reachability test. nc -u only sends data when you type something on stdin, and even if a packet does get through, a Minecraft Bedrock server will not reply to arbitrary non-RakNet bytes. This result tells us nothing about whether the port is actually reachable.

2. The incoming a new work connection for udp proxy log does not mean user traffic arrived. frps proactively pre-establishes a UDP work connection ~500 ms after the proxy starts (server/proxy/udp.go). So the line you see is just the control-plane setup — we still have no evidence that any real Bedrock / Voice Chat packet ever reached frps.

3. Client 1 → Proxy 1 (.171) connection write timeout points at a blocked UDP 7000 on that host. Your clients use transport.protocol = "kcp", i.e. the control connection runs over UDP/7000. Client 2 logs in to Proxy 2 (.172) fine with the same config, while Client 1 times out against .171. That strongly suggests the .171 server's UDP/7000 is blocked somewhere (cloud security group, ufw/iptables, or upstream network).

4. To actually locate where UDP is dropping, please run tcpdump on both sides while a real Bedrock client tries to connect.

On the frps host:

sudo tcpdump -ni any udp port 19132

On the frpc host (at the same time):

sudo tcpdump -ni any udp and host 172.18.0.1 and port 19132

Then try connecting from a real Minecraft Bedrock client (not nc). This splits the path into three segments:

  • player → frps (visible on the server-side capture)
  • frps → frpc (handled internally over the work connection; if the server capture shows packets but the Bedrock server still doesn't respond, this segment is fine)
  • frpc → 172.18.0.1:19132 (visible on the client-side capture)

Whichever capture is empty is the broken segment. Please share both captures plus the output of sudo iptables -S / ufw status verbose and your cloud provider's security group rules for UDP.

Also please confirm: is 172.18.0.1:19132 the Docker bridge gateway, or the container IP of the Bedrock server? If it's the gateway, you need a port publish (-p 19132:19132/udp) on the container so the gateway actually has something listening.

<!-- gh-comment-id:4250360068 --> @fatedier commented on GitHub (Apr 15, 2026): Thanks for the details. A few observations: **1. `nc -u ... 19132` → "no reply" is not a valid reachability test.** `nc -u` only sends data when you type something on stdin, and even if a packet does get through, a Minecraft Bedrock server will not reply to arbitrary non-RakNet bytes. This result tells us nothing about whether the port is actually reachable. **2. The `incoming a new work connection for udp proxy` log does not mean user traffic arrived.** frps proactively pre-establishes a UDP work connection ~500 ms after the proxy starts (`server/proxy/udp.go`). So the line you see is just the control-plane setup — we still have no evidence that any real Bedrock / Voice Chat packet ever reached frps. **3. Client 1 → Proxy 1 (`.171`) `connection write timeout` points at a blocked UDP 7000 on that host.** Your clients use `transport.protocol = "kcp"`, i.e. the control connection runs over UDP/7000. Client 2 logs in to Proxy 2 (`.172`) fine with the same config, while Client 1 times out against `.171`. That strongly suggests the `.171` server's UDP/7000 is blocked somewhere (cloud security group, `ufw`/`iptables`, or upstream network). **4. To actually locate where UDP is dropping, please run `tcpdump` on both sides while a real Bedrock client tries to connect.** On the frps host: ```bash sudo tcpdump -ni any udp port 19132 ``` On the frpc host (at the same time): ```bash sudo tcpdump -ni any udp and host 172.18.0.1 and port 19132 ``` Then try connecting from a real Minecraft Bedrock client (not `nc`). This splits the path into three segments: - player → frps (visible on the server-side capture) - frps → frpc (handled internally over the work connection; if the server capture shows packets but the Bedrock server still doesn't respond, this segment is fine) - frpc → `172.18.0.1:19132` (visible on the client-side capture) Whichever capture is empty is the broken segment. Please share both captures plus the output of `sudo iptables -S` / `ufw status verbose` and your cloud provider's security group rules for UDP. Also please confirm: is `172.18.0.1:19132` the Docker bridge gateway, or the container IP of the Bedrock server? If it's the gateway, you need a port publish (`-p 19132:19132/udp`) on the container so the gateway actually has something listening.
Author
Owner

@liam6080 commented on GitHub (Apr 15, 2026):

Hello,

I can see on the server:

08:28:40.034615 eth0  In  IP 14.X.X.X.44130 > 62.72.177.172.19132: UDP, length 1172
08:28:40.034638 eth0  Out IP 62.72.177.172.44130 > 45.X.X.X.19132: UDP, length 1172

On the client:

# sudo tcpdump -ni any udp and host 172.18.0.1 and port 19132
tcpdump: data link type LINUX_SLL2
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes
# sudo tcpdump -ni any udp and port 19132
09:16:03.714741 enp1s0f0 In  IP 62.72.177.172.36251 > 45.XXX.XXX.XXX.19132: UDP, length 33
# ss -lunp | grep 19132
UNCONN 0      0         172.18.0.1:19132      0.0.0.0:*    users:(("docker-proxy",pid=7290,fd=8))

# ss -lunp | grep 30004
UNCONN 0      0         172.18.0.1:30004      0.0.0.0:*    users:(("docker-proxy",pid=7345,fd=8)) 

UFW is only set on the client: "java works via haproxy"

Status: active
Logging: on (low)
Default: deny (incoming), allow (outgoing), deny (routed)
New profiles: skip

To                         Action      From
--                         ------      ----
22/tcp                     ALLOW IN    Anywhere                  
80                         ALLOW IN    Anywhere                  
443                        ALLOW IN    Anywhere                  
8080                       ALLOW IN    Anywhere                  
2022                       ALLOW IN    Anywhere                  
3306                       ALLOW IN    Anywhere                  
172.18.0.1 25567/tcp on pterodactyl0 ALLOW IN    Anywhere                  
172.18.0.1 25566/tcp on pterodactyl0 ALLOW IN    Anywhere                  
172.18.0.1 25568/tcp on pterodactyl0 ALLOW IN    Anywhere                  
172.18.0.1 25565/tcp on pterodactyl0 ALLOW IN    Anywhere                  
172.18.0.1 25570/tcp on pterodactyl0 ALLOW IN    Anywhere                  
22                         ALLOW IN    Anywhere                  
25565/tcp                  ALLOW IN    62.72.177.172             
25565/tcp                  ALLOW IN    62.72.177.171             
25565/tcp                  DENY IN     Anywhere                  
172.18.0.1 19132/udp on pterodactyl0 ALLOW IN    Anywhere                  
172.18.0.1 30004/udp on pterodactyl0 ALLOW IN    Anywhere                  
30004/udp                  ALLOW IN    62.72.177.171             
19132/udp                  ALLOW IN    62.72.177.171             
19132/udp                  ALLOW IN    62.72.177.172             
30004/udp                  ALLOW IN    62.72.177.172             
172.18.0.1 30010/udp on pterodactyl0 ALLOW IN    Anywhere                  
30100/udp                  ALLOW IN    62.72.177.172             
19194/udp                  ALLOW IN    62.72.177.172             
19194/udp                  ALLOW IN    62.72.177.171             
30100/udp                  ALLOW IN    62.72.177.171

iptables: "Should not be working due to UFW else it removes iptables anyway when UFW is in use yet it works for haproxy/java"

# sudo iptables -S
-P INPUT DROP
-P FORWARD DROP
-P OUTPUT ACCEPT
-N DOCKER
-N DOCKER-BRIDGE
-N DOCKER-CT
-N DOCKER-FORWARD
-N DOCKER-INTERNAL
-N DOCKER-USER
-N ufw-after-forward
-N ufw-after-input
-N ufw-after-logging-forward
-N ufw-after-logging-input
-N ufw-after-logging-output
-N ufw-after-output
-N ufw-before-forward
-N ufw-before-input
-N ufw-before-logging-forward
-N ufw-before-logging-input
-N ufw-before-logging-output
-N ufw-before-output
-N ufw-logging-allow
-N ufw-logging-deny
-N ufw-not-local
-N ufw-reject-forward
-N ufw-reject-input
-N ufw-reject-output
-N ufw-skip-to-policy-forward
-N ufw-skip-to-policy-input
-N ufw-skip-to-policy-output
-N ufw-track-forward
-N ufw-track-input
-N ufw-track-output
-N ufw-user-forward
-N ufw-user-input
-N ufw-user-limit
-N ufw-user-limit-accept
-N ufw-user-logging-forward
-N ufw-user-logging-input
-N ufw-user-logging-output
-N ufw-user-output
-A INPUT -j ufw-before-logging-input
-A INPUT -j ufw-before-input
-A INPUT -j ufw-after-input
-A INPUT -j ufw-after-logging-input
-A INPUT -j ufw-reject-input
-A INPUT -j ufw-track-input
-A FORWARD -j DOCKER-USER
-A FORWARD -j DOCKER-FORWARD
-A FORWARD -j ufw-before-logging-forward
-A FORWARD -j ufw-before-forward
-A FORWARD -j ufw-after-forward
-A FORWARD -j ufw-after-logging-forward
-A FORWARD -j ufw-reject-forward
-A FORWARD -j ufw-track-forward
-A OUTPUT -j ufw-before-logging-output
-A OUTPUT -j ufw-before-output
-A OUTPUT -j ufw-after-output
-A OUTPUT -j ufw-after-logging-output
-A OUTPUT -j ufw-reject-output
-A OUTPUT -j ufw-track-output
-A DOCKER -d 172.18.0.10/32 ! -i pterodactyl0 -o pterodactyl0 -p udp -m udp --dport 25570 -j ACCEPT
-A DOCKER -d 172.18.0.10/32 ! -i pterodactyl0 -o pterodactyl0 -p tcp -m tcp --dport 25570 -j ACCEPT
-A DOCKER -d 172.18.0.12/32 ! -i pterodactyl0 -o pterodactyl0 -p udp -m udp --dport 25574 -j ACCEPT
-A DOCKER -d 172.18.0.12/32 ! -i pterodactyl0 -o pterodactyl0 -p tcp -m tcp --dport 25574 -j ACCEPT
-A DOCKER -d 172.18.0.11/32 ! -i pterodactyl0 -o pterodactyl0 -p udp -m udp --dport 25569 -j ACCEPT
-A DOCKER -d 172.18.0.11/32 ! -i pterodactyl0 -o pterodactyl0 -p tcp -m tcp --dport 25569 -j ACCEPT
-A DOCKER -d 172.18.0.9/32 ! -i pterodactyl0 -o pterodactyl0 -p udp -m udp --dport 30010 -j ACCEPT
-A DOCKER -d 172.18.0.9/32 ! -i pterodactyl0 -o pterodactyl0 -p tcp -m tcp --dport 30010 -j ACCEPT
-A DOCKER -d 172.18.0.9/32 ! -i pterodactyl0 -o pterodactyl0 -p udp -m udp --dport 25566 -j ACCEPT
-A DOCKER -d 172.18.0.9/32 ! -i pterodactyl0 -o pterodactyl0 -p tcp -m tcp --dport 25566 -j ACCEPT
-A DOCKER -d 172.18.0.8/32 ! -i pterodactyl0 -o pterodactyl0 -p udp -m udp --dport 30001 -j ACCEPT
-A DOCKER -d 172.18.0.8/32 ! -i pterodactyl0 -o pterodactyl0 -p tcp -m tcp --dport 30001 -j ACCEPT
-A DOCKER -d 172.18.0.7/32 ! -i pterodactyl0 -o pterodactyl0 -p udp -m udp --dport 25571 -j ACCEPT
-A DOCKER -d 172.18.0.7/32 ! -i pterodactyl0 -o pterodactyl0 -p tcp -m tcp --dport 25571 -j ACCEPT
-A DOCKER -d 172.18.0.6/32 ! -i pterodactyl0 -o pterodactyl0 -p udp -m udp --dport 25573 -j ACCEPT
-A DOCKER -d 172.18.0.6/32 ! -i pterodactyl0 -o pterodactyl0 -p tcp -m tcp --dport 25573 -j ACCEPT
-A DOCKER -d 172.18.0.5/32 ! -i pterodactyl0 -o pterodactyl0 -p udp -m udp --dport 25568 -j ACCEPT
-A DOCKER -d 172.18.0.5/32 ! -i pterodactyl0 -o pterodactyl0 -p tcp -m tcp --dport 25568 -j ACCEPT
-A DOCKER -d 172.18.0.4/32 ! -i pterodactyl0 -o pterodactyl0 -p udp -m udp --dport 25567 -j ACCEPT
-A DOCKER -d 172.18.0.4/32 ! -i pterodactyl0 -o pterodactyl0 -p tcp -m tcp --dport 25567 -j ACCEPT
-A DOCKER -d 172.18.0.3/32 ! -i pterodactyl0 -o pterodactyl0 -p udp -m udp --dport 25568 -j ACCEPT
-A DOCKER -d 172.18.0.3/32 ! -i pterodactyl0 -o pterodactyl0 -p tcp -m tcp --dport 25568 -j ACCEPT
-A DOCKER -d 172.18.0.2/32 ! -i pterodactyl0 -o pterodactyl0 -p udp -m udp --dport 30004 -j ACCEPT
-A DOCKER -d 172.18.0.2/32 ! -i pterodactyl0 -o pterodactyl0 -p tcp -m tcp --dport 30004 -j ACCEPT
-A DOCKER -d 172.18.0.2/32 ! -i pterodactyl0 -o pterodactyl0 -p udp -m udp --dport 25565 -j ACCEPT
-A DOCKER -d 172.18.0.2/32 ! -i pterodactyl0 -o pterodactyl0 -p tcp -m tcp --dport 25565 -j ACCEPT
-A DOCKER -d 172.18.0.2/32 ! -i pterodactyl0 -o pterodactyl0 -p udp -m udp --dport 19132 -j ACCEPT
-A DOCKER -d 172.18.0.2/32 ! -i pterodactyl0 -o pterodactyl0 -p tcp -m tcp --dport 19132 -j ACCEPT
-A DOCKER ! -i pterodactyl0 -o pterodactyl0 -j DROP
-A DOCKER ! -i docker0 -o docker0 -j DROP
-A DOCKER ! -i br-4f151f66dcaa -o br-4f151f66dcaa -j DROP
-A DOCKER-BRIDGE -o pterodactyl0 -j DOCKER
-A DOCKER-BRIDGE -o docker0 -j DOCKER
-A DOCKER-BRIDGE -o br-4f151f66dcaa -j DOCKER
-A DOCKER-CT -o pterodactyl0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A DOCKER-CT -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A DOCKER-CT -o br-4f151f66dcaa -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A DOCKER-FORWARD -j DOCKER-CT
-A DOCKER-FORWARD -j DOCKER-INTERNAL
-A DOCKER-FORWARD -j DOCKER-BRIDGE
-A DOCKER-FORWARD -i pterodactyl0 -j ACCEPT
-A DOCKER-FORWARD -i docker0 -j ACCEPT
-A DOCKER-FORWARD -i br-4f151f66dcaa -j ACCEPT
-A ufw-after-input -p udp -m udp --dport 137 -j ufw-skip-to-policy-input
-A ufw-after-input -p udp -m udp --dport 138 -j ufw-skip-to-policy-input
-A ufw-after-input -p tcp -m tcp --dport 139 -j ufw-skip-to-policy-input
-A ufw-after-input -p tcp -m tcp --dport 445 -j ufw-skip-to-policy-input
-A ufw-after-input -p udp -m udp --dport 67 -j ufw-skip-to-policy-input
-A ufw-after-input -p udp -m udp --dport 68 -j ufw-skip-to-policy-input
-A ufw-after-input -m addrtype --dst-type BROADCAST -j ufw-skip-to-policy-input
-A ufw-after-logging-forward -m limit --limit 3/min --limit-burst 10 -j LOG --log-prefix "[UFW BLOCK] "
-A ufw-after-logging-input -m limit --limit 3/min --limit-burst 10 -j LOG --log-prefix "[UFW BLOCK] "
-A ufw-before-forward -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A ufw-before-forward -p icmp -m icmp --icmp-type 3 -j ACCEPT
-A ufw-before-forward -p icmp -m icmp --icmp-type 11 -j ACCEPT
-A ufw-before-forward -p icmp -m icmp --icmp-type 12 -j ACCEPT
-A ufw-before-forward -p icmp -m icmp --icmp-type 8 -j ACCEPT
-A ufw-before-forward -j ufw-user-forward
-A ufw-before-input -i lo -j ACCEPT
-A ufw-before-input -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A ufw-before-input -m conntrack --ctstate INVALID -j ufw-logging-deny
-A ufw-before-input -m conntrack --ctstate INVALID -j DROP
-A ufw-before-input -p icmp -m icmp --icmp-type 3 -j ACCEPT
-A ufw-before-input -p icmp -m icmp --icmp-type 11 -j ACCEPT
-A ufw-before-input -p icmp -m icmp --icmp-type 12 -j ACCEPT
-A ufw-before-input -p icmp -m icmp --icmp-type 8 -j ACCEPT
-A ufw-before-input -p udp -m udp --sport 67 --dport 68 -j ACCEPT
-A ufw-before-input -j ufw-not-local
-A ufw-before-input -d 224.0.0.251/32 -p udp -m udp --dport 5353 -j ACCEPT
-A ufw-before-input -d 239.255.255.250/32 -p udp -m udp --dport 1900 -j ACCEPT
-A ufw-before-input -j ufw-user-input
-A ufw-before-output -o lo -j ACCEPT
-A ufw-before-output -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A ufw-before-output -j ufw-user-output
-A ufw-logging-allow -m limit --limit 3/min --limit-burst 10 -j LOG --log-prefix "[UFW ALLOW] "
-A ufw-logging-deny -m conntrack --ctstate INVALID -m limit --limit 3/min --limit-burst 10 -j RETURN
-A ufw-logging-deny -m limit --limit 3/min --limit-burst 10 -j LOG --log-prefix "[UFW BLOCK] "
-A ufw-not-local -m addrtype --dst-type LOCAL -j RETURN
-A ufw-not-local -m addrtype --dst-type MULTICAST -j RETURN
-A ufw-not-local -m addrtype --dst-type BROADCAST -j RETURN
-A ufw-not-local -m limit --limit 3/min --limit-burst 10 -j ufw-logging-deny
-A ufw-not-local -j DROP
-A ufw-skip-to-policy-forward -j DROP
-A ufw-skip-to-policy-input -j DROP
-A ufw-skip-to-policy-output -j ACCEPT
-A ufw-track-output -p tcp -m conntrack --ctstate NEW -j ACCEPT
-A ufw-track-output -p udp -m conntrack --ctstate NEW -j ACCEPT
-A ufw-user-input -p tcp -m tcp --dport 22 -j ACCEPT
-A ufw-user-input -p tcp -m tcp --dport 80 -j ACCEPT
-A ufw-user-input -p udp -m udp --dport 80 -j ACCEPT
-A ufw-user-input -p tcp -m tcp --dport 443 -j ACCEPT
-A ufw-user-input -p udp -m udp --dport 443 -j ACCEPT
-A ufw-user-input -p tcp -m tcp --dport 8080 -j ACCEPT
-A ufw-user-input -p udp -m udp --dport 8080 -j ACCEPT
-A ufw-user-input -p tcp -m tcp --dport 2022 -j ACCEPT
-A ufw-user-input -p udp -m udp --dport 2022 -j ACCEPT
-A ufw-user-input -p tcp -m tcp --dport 3306 -j ACCEPT
-A ufw-user-input -p udp -m udp --dport 3306 -j ACCEPT
-A ufw-user-input -d 172.18.0.1/32 -i pterodactyl0 -p tcp -m tcp --dport 25567 -j ACCEPT
-A ufw-user-input -d 172.18.0.1/32 -i pterodactyl0 -p tcp -m tcp --dport 25566 -j ACCEPT
-A ufw-user-input -d 172.18.0.1/32 -i pterodactyl0 -p tcp -m tcp --dport 25568 -j ACCEPT
-A ufw-user-input -d 172.18.0.1/32 -i pterodactyl0 -p tcp -m tcp --dport 25565 -j ACCEPT
-A ufw-user-input -d 172.18.0.1/32 -i pterodactyl0 -p tcp -m tcp --dport 25570 -j ACCEPT
-A ufw-user-input -p tcp -m tcp --dport 22 -j ACCEPT
-A ufw-user-input -p udp -m udp --dport 22 -j ACCEPT
-A ufw-user-input -s 62.72.177.172/32 -p tcp -m tcp --dport 25565 -j ACCEPT
-A ufw-user-input -s 62.72.177.171/32 -p tcp -m tcp --dport 25565 -j ACCEPT
-A ufw-user-input -p tcp -m tcp --dport 25565 -j DROP
-A ufw-user-input -d 172.18.0.1/32 -i pterodactyl0 -p udp -m udp --dport 19132 -j ACCEPT
-A ufw-user-input -d 172.18.0.1/32 -i pterodactyl0 -p udp -m udp --dport 30004 -j ACCEPT
-A ufw-user-input -s 62.72.177.171/32 -p udp -m udp --dport 30004 -j ACCEPT
-A ufw-user-input -s 62.72.177.171/32 -p udp -m udp --dport 19132 -j ACCEPT
-A ufw-user-input -s 62.72.177.172/32 -p udp -m udp --dport 19132 -j ACCEPT
-A ufw-user-input -s 62.72.177.172/32 -p udp -m udp --dport 30004 -j ACCEPT
-A ufw-user-input -d 172.18.0.1/32 -i pterodactyl0 -p udp -m udp --dport 30010 -j ACCEPT
-A ufw-user-input -s 62.72.177.172/32 -p udp -m udp --dport 30100 -j ACCEPT
-A ufw-user-input -s 62.72.177.172/32 -p udp -m udp --dport 19194 -j ACCEPT
-A ufw-user-input -s 62.72.177.171/32 -p udp -m udp --dport 19194 -j ACCEPT
-A ufw-user-input -s 62.72.177.171/32 -p udp -m udp --dport 30100 -j ACCEPT
-A ufw-user-limit -m limit --limit 3/min -j LOG --log-prefix "[UFW LIMIT BLOCK] "
-A ufw-user-limit -j REJECT --reject-with icmp-port-unreachable
-A ufw-user-limit-accept -j ACCEPT
<!-- gh-comment-id:4250457033 --> @liam6080 commented on GitHub (Apr 15, 2026): Hello, I can see on the server: ``` 08:28:40.034615 eth0 In IP 14.X.X.X.44130 > 62.72.177.172.19132: UDP, length 1172 08:28:40.034638 eth0 Out IP 62.72.177.172.44130 > 45.X.X.X.19132: UDP, length 1172 ``` On the client: ``` # sudo tcpdump -ni any udp and host 172.18.0.1 and port 19132 tcpdump: data link type LINUX_SLL2 tcpdump: verbose output suppressed, use -v[v]... for full protocol decode listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes ``` ``` # sudo tcpdump -ni any udp and port 19132 09:16:03.714741 enp1s0f0 In IP 62.72.177.172.36251 > 45.XXX.XXX.XXX.19132: UDP, length 33 ``` ``` # ss -lunp | grep 19132 UNCONN 0 0 172.18.0.1:19132 0.0.0.0:* users:(("docker-proxy",pid=7290,fd=8)) # ss -lunp | grep 30004 UNCONN 0 0 172.18.0.1:30004 0.0.0.0:* users:(("docker-proxy",pid=7345,fd=8)) ``` UFW is only set on the client: "java works via haproxy" ``` Status: active Logging: on (low) Default: deny (incoming), allow (outgoing), deny (routed) New profiles: skip To Action From -- ------ ---- 22/tcp ALLOW IN Anywhere 80 ALLOW IN Anywhere 443 ALLOW IN Anywhere 8080 ALLOW IN Anywhere 2022 ALLOW IN Anywhere 3306 ALLOW IN Anywhere 172.18.0.1 25567/tcp on pterodactyl0 ALLOW IN Anywhere 172.18.0.1 25566/tcp on pterodactyl0 ALLOW IN Anywhere 172.18.0.1 25568/tcp on pterodactyl0 ALLOW IN Anywhere 172.18.0.1 25565/tcp on pterodactyl0 ALLOW IN Anywhere 172.18.0.1 25570/tcp on pterodactyl0 ALLOW IN Anywhere 22 ALLOW IN Anywhere 25565/tcp ALLOW IN 62.72.177.172 25565/tcp ALLOW IN 62.72.177.171 25565/tcp DENY IN Anywhere 172.18.0.1 19132/udp on pterodactyl0 ALLOW IN Anywhere 172.18.0.1 30004/udp on pterodactyl0 ALLOW IN Anywhere 30004/udp ALLOW IN 62.72.177.171 19132/udp ALLOW IN 62.72.177.171 19132/udp ALLOW IN 62.72.177.172 30004/udp ALLOW IN 62.72.177.172 172.18.0.1 30010/udp on pterodactyl0 ALLOW IN Anywhere 30100/udp ALLOW IN 62.72.177.172 19194/udp ALLOW IN 62.72.177.172 19194/udp ALLOW IN 62.72.177.171 30100/udp ALLOW IN 62.72.177.171 ``` iptables: "Should not be working due to UFW else it removes iptables anyway when UFW is in use yet it works for haproxy/java" ``` # sudo iptables -S -P INPUT DROP -P FORWARD DROP -P OUTPUT ACCEPT -N DOCKER -N DOCKER-BRIDGE -N DOCKER-CT -N DOCKER-FORWARD -N DOCKER-INTERNAL -N DOCKER-USER -N ufw-after-forward -N ufw-after-input -N ufw-after-logging-forward -N ufw-after-logging-input -N ufw-after-logging-output -N ufw-after-output -N ufw-before-forward -N ufw-before-input -N ufw-before-logging-forward -N ufw-before-logging-input -N ufw-before-logging-output -N ufw-before-output -N ufw-logging-allow -N ufw-logging-deny -N ufw-not-local -N ufw-reject-forward -N ufw-reject-input -N ufw-reject-output -N ufw-skip-to-policy-forward -N ufw-skip-to-policy-input -N ufw-skip-to-policy-output -N ufw-track-forward -N ufw-track-input -N ufw-track-output -N ufw-user-forward -N ufw-user-input -N ufw-user-limit -N ufw-user-limit-accept -N ufw-user-logging-forward -N ufw-user-logging-input -N ufw-user-logging-output -N ufw-user-output -A INPUT -j ufw-before-logging-input -A INPUT -j ufw-before-input -A INPUT -j ufw-after-input -A INPUT -j ufw-after-logging-input -A INPUT -j ufw-reject-input -A INPUT -j ufw-track-input -A FORWARD -j DOCKER-USER -A FORWARD -j DOCKER-FORWARD -A FORWARD -j ufw-before-logging-forward -A FORWARD -j ufw-before-forward -A FORWARD -j ufw-after-forward -A FORWARD -j ufw-after-logging-forward -A FORWARD -j ufw-reject-forward -A FORWARD -j ufw-track-forward -A OUTPUT -j ufw-before-logging-output -A OUTPUT -j ufw-before-output -A OUTPUT -j ufw-after-output -A OUTPUT -j ufw-after-logging-output -A OUTPUT -j ufw-reject-output -A OUTPUT -j ufw-track-output -A DOCKER -d 172.18.0.10/32 ! -i pterodactyl0 -o pterodactyl0 -p udp -m udp --dport 25570 -j ACCEPT -A DOCKER -d 172.18.0.10/32 ! -i pterodactyl0 -o pterodactyl0 -p tcp -m tcp --dport 25570 -j ACCEPT -A DOCKER -d 172.18.0.12/32 ! -i pterodactyl0 -o pterodactyl0 -p udp -m udp --dport 25574 -j ACCEPT -A DOCKER -d 172.18.0.12/32 ! -i pterodactyl0 -o pterodactyl0 -p tcp -m tcp --dport 25574 -j ACCEPT -A DOCKER -d 172.18.0.11/32 ! -i pterodactyl0 -o pterodactyl0 -p udp -m udp --dport 25569 -j ACCEPT -A DOCKER -d 172.18.0.11/32 ! -i pterodactyl0 -o pterodactyl0 -p tcp -m tcp --dport 25569 -j ACCEPT -A DOCKER -d 172.18.0.9/32 ! -i pterodactyl0 -o pterodactyl0 -p udp -m udp --dport 30010 -j ACCEPT -A DOCKER -d 172.18.0.9/32 ! -i pterodactyl0 -o pterodactyl0 -p tcp -m tcp --dport 30010 -j ACCEPT -A DOCKER -d 172.18.0.9/32 ! -i pterodactyl0 -o pterodactyl0 -p udp -m udp --dport 25566 -j ACCEPT -A DOCKER -d 172.18.0.9/32 ! -i pterodactyl0 -o pterodactyl0 -p tcp -m tcp --dport 25566 -j ACCEPT -A DOCKER -d 172.18.0.8/32 ! -i pterodactyl0 -o pterodactyl0 -p udp -m udp --dport 30001 -j ACCEPT -A DOCKER -d 172.18.0.8/32 ! -i pterodactyl0 -o pterodactyl0 -p tcp -m tcp --dport 30001 -j ACCEPT -A DOCKER -d 172.18.0.7/32 ! -i pterodactyl0 -o pterodactyl0 -p udp -m udp --dport 25571 -j ACCEPT -A DOCKER -d 172.18.0.7/32 ! -i pterodactyl0 -o pterodactyl0 -p tcp -m tcp --dport 25571 -j ACCEPT -A DOCKER -d 172.18.0.6/32 ! -i pterodactyl0 -o pterodactyl0 -p udp -m udp --dport 25573 -j ACCEPT -A DOCKER -d 172.18.0.6/32 ! -i pterodactyl0 -o pterodactyl0 -p tcp -m tcp --dport 25573 -j ACCEPT -A DOCKER -d 172.18.0.5/32 ! -i pterodactyl0 -o pterodactyl0 -p udp -m udp --dport 25568 -j ACCEPT -A DOCKER -d 172.18.0.5/32 ! -i pterodactyl0 -o pterodactyl0 -p tcp -m tcp --dport 25568 -j ACCEPT -A DOCKER -d 172.18.0.4/32 ! -i pterodactyl0 -o pterodactyl0 -p udp -m udp --dport 25567 -j ACCEPT -A DOCKER -d 172.18.0.4/32 ! -i pterodactyl0 -o pterodactyl0 -p tcp -m tcp --dport 25567 -j ACCEPT -A DOCKER -d 172.18.0.3/32 ! -i pterodactyl0 -o pterodactyl0 -p udp -m udp --dport 25568 -j ACCEPT -A DOCKER -d 172.18.0.3/32 ! -i pterodactyl0 -o pterodactyl0 -p tcp -m tcp --dport 25568 -j ACCEPT -A DOCKER -d 172.18.0.2/32 ! -i pterodactyl0 -o pterodactyl0 -p udp -m udp --dport 30004 -j ACCEPT -A DOCKER -d 172.18.0.2/32 ! -i pterodactyl0 -o pterodactyl0 -p tcp -m tcp --dport 30004 -j ACCEPT -A DOCKER -d 172.18.0.2/32 ! -i pterodactyl0 -o pterodactyl0 -p udp -m udp --dport 25565 -j ACCEPT -A DOCKER -d 172.18.0.2/32 ! -i pterodactyl0 -o pterodactyl0 -p tcp -m tcp --dport 25565 -j ACCEPT -A DOCKER -d 172.18.0.2/32 ! -i pterodactyl0 -o pterodactyl0 -p udp -m udp --dport 19132 -j ACCEPT -A DOCKER -d 172.18.0.2/32 ! -i pterodactyl0 -o pterodactyl0 -p tcp -m tcp --dport 19132 -j ACCEPT -A DOCKER ! -i pterodactyl0 -o pterodactyl0 -j DROP -A DOCKER ! -i docker0 -o docker0 -j DROP -A DOCKER ! -i br-4f151f66dcaa -o br-4f151f66dcaa -j DROP -A DOCKER-BRIDGE -o pterodactyl0 -j DOCKER -A DOCKER-BRIDGE -o docker0 -j DOCKER -A DOCKER-BRIDGE -o br-4f151f66dcaa -j DOCKER -A DOCKER-CT -o pterodactyl0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -A DOCKER-CT -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -A DOCKER-CT -o br-4f151f66dcaa -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -A DOCKER-FORWARD -j DOCKER-CT -A DOCKER-FORWARD -j DOCKER-INTERNAL -A DOCKER-FORWARD -j DOCKER-BRIDGE -A DOCKER-FORWARD -i pterodactyl0 -j ACCEPT -A DOCKER-FORWARD -i docker0 -j ACCEPT -A DOCKER-FORWARD -i br-4f151f66dcaa -j ACCEPT -A ufw-after-input -p udp -m udp --dport 137 -j ufw-skip-to-policy-input -A ufw-after-input -p udp -m udp --dport 138 -j ufw-skip-to-policy-input -A ufw-after-input -p tcp -m tcp --dport 139 -j ufw-skip-to-policy-input -A ufw-after-input -p tcp -m tcp --dport 445 -j ufw-skip-to-policy-input -A ufw-after-input -p udp -m udp --dport 67 -j ufw-skip-to-policy-input -A ufw-after-input -p udp -m udp --dport 68 -j ufw-skip-to-policy-input -A ufw-after-input -m addrtype --dst-type BROADCAST -j ufw-skip-to-policy-input -A ufw-after-logging-forward -m limit --limit 3/min --limit-burst 10 -j LOG --log-prefix "[UFW BLOCK] " -A ufw-after-logging-input -m limit --limit 3/min --limit-burst 10 -j LOG --log-prefix "[UFW BLOCK] " -A ufw-before-forward -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -A ufw-before-forward -p icmp -m icmp --icmp-type 3 -j ACCEPT -A ufw-before-forward -p icmp -m icmp --icmp-type 11 -j ACCEPT -A ufw-before-forward -p icmp -m icmp --icmp-type 12 -j ACCEPT -A ufw-before-forward -p icmp -m icmp --icmp-type 8 -j ACCEPT -A ufw-before-forward -j ufw-user-forward -A ufw-before-input -i lo -j ACCEPT -A ufw-before-input -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -A ufw-before-input -m conntrack --ctstate INVALID -j ufw-logging-deny -A ufw-before-input -m conntrack --ctstate INVALID -j DROP -A ufw-before-input -p icmp -m icmp --icmp-type 3 -j ACCEPT -A ufw-before-input -p icmp -m icmp --icmp-type 11 -j ACCEPT -A ufw-before-input -p icmp -m icmp --icmp-type 12 -j ACCEPT -A ufw-before-input -p icmp -m icmp --icmp-type 8 -j ACCEPT -A ufw-before-input -p udp -m udp --sport 67 --dport 68 -j ACCEPT -A ufw-before-input -j ufw-not-local -A ufw-before-input -d 224.0.0.251/32 -p udp -m udp --dport 5353 -j ACCEPT -A ufw-before-input -d 239.255.255.250/32 -p udp -m udp --dport 1900 -j ACCEPT -A ufw-before-input -j ufw-user-input -A ufw-before-output -o lo -j ACCEPT -A ufw-before-output -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -A ufw-before-output -j ufw-user-output -A ufw-logging-allow -m limit --limit 3/min --limit-burst 10 -j LOG --log-prefix "[UFW ALLOW] " -A ufw-logging-deny -m conntrack --ctstate INVALID -m limit --limit 3/min --limit-burst 10 -j RETURN -A ufw-logging-deny -m limit --limit 3/min --limit-burst 10 -j LOG --log-prefix "[UFW BLOCK] " -A ufw-not-local -m addrtype --dst-type LOCAL -j RETURN -A ufw-not-local -m addrtype --dst-type MULTICAST -j RETURN -A ufw-not-local -m addrtype --dst-type BROADCAST -j RETURN -A ufw-not-local -m limit --limit 3/min --limit-burst 10 -j ufw-logging-deny -A ufw-not-local -j DROP -A ufw-skip-to-policy-forward -j DROP -A ufw-skip-to-policy-input -j DROP -A ufw-skip-to-policy-output -j ACCEPT -A ufw-track-output -p tcp -m conntrack --ctstate NEW -j ACCEPT -A ufw-track-output -p udp -m conntrack --ctstate NEW -j ACCEPT -A ufw-user-input -p tcp -m tcp --dport 22 -j ACCEPT -A ufw-user-input -p tcp -m tcp --dport 80 -j ACCEPT -A ufw-user-input -p udp -m udp --dport 80 -j ACCEPT -A ufw-user-input -p tcp -m tcp --dport 443 -j ACCEPT -A ufw-user-input -p udp -m udp --dport 443 -j ACCEPT -A ufw-user-input -p tcp -m tcp --dport 8080 -j ACCEPT -A ufw-user-input -p udp -m udp --dport 8080 -j ACCEPT -A ufw-user-input -p tcp -m tcp --dport 2022 -j ACCEPT -A ufw-user-input -p udp -m udp --dport 2022 -j ACCEPT -A ufw-user-input -p tcp -m tcp --dport 3306 -j ACCEPT -A ufw-user-input -p udp -m udp --dport 3306 -j ACCEPT -A ufw-user-input -d 172.18.0.1/32 -i pterodactyl0 -p tcp -m tcp --dport 25567 -j ACCEPT -A ufw-user-input -d 172.18.0.1/32 -i pterodactyl0 -p tcp -m tcp --dport 25566 -j ACCEPT -A ufw-user-input -d 172.18.0.1/32 -i pterodactyl0 -p tcp -m tcp --dport 25568 -j ACCEPT -A ufw-user-input -d 172.18.0.1/32 -i pterodactyl0 -p tcp -m tcp --dport 25565 -j ACCEPT -A ufw-user-input -d 172.18.0.1/32 -i pterodactyl0 -p tcp -m tcp --dport 25570 -j ACCEPT -A ufw-user-input -p tcp -m tcp --dport 22 -j ACCEPT -A ufw-user-input -p udp -m udp --dport 22 -j ACCEPT -A ufw-user-input -s 62.72.177.172/32 -p tcp -m tcp --dport 25565 -j ACCEPT -A ufw-user-input -s 62.72.177.171/32 -p tcp -m tcp --dport 25565 -j ACCEPT -A ufw-user-input -p tcp -m tcp --dport 25565 -j DROP -A ufw-user-input -d 172.18.0.1/32 -i pterodactyl0 -p udp -m udp --dport 19132 -j ACCEPT -A ufw-user-input -d 172.18.0.1/32 -i pterodactyl0 -p udp -m udp --dport 30004 -j ACCEPT -A ufw-user-input -s 62.72.177.171/32 -p udp -m udp --dport 30004 -j ACCEPT -A ufw-user-input -s 62.72.177.171/32 -p udp -m udp --dport 19132 -j ACCEPT -A ufw-user-input -s 62.72.177.172/32 -p udp -m udp --dport 19132 -j ACCEPT -A ufw-user-input -s 62.72.177.172/32 -p udp -m udp --dport 30004 -j ACCEPT -A ufw-user-input -d 172.18.0.1/32 -i pterodactyl0 -p udp -m udp --dport 30010 -j ACCEPT -A ufw-user-input -s 62.72.177.172/32 -p udp -m udp --dport 30100 -j ACCEPT -A ufw-user-input -s 62.72.177.172/32 -p udp -m udp --dport 19194 -j ACCEPT -A ufw-user-input -s 62.72.177.171/32 -p udp -m udp --dport 19194 -j ACCEPT -A ufw-user-input -s 62.72.177.171/32 -p udp -m udp --dport 30100 -j ACCEPT -A ufw-user-limit -m limit --limit 3/min -j LOG --log-prefix "[UFW LIMIT BLOCK] " -A ufw-user-limit -j REJECT --reject-with icmp-port-unreachable -A ufw-user-limit-accept -j ACCEPT ```
Author
Owner

@liam6080 commented on GitHub (Apr 16, 2026):

Hello,

As a update, I was able to get it to work by changing the bedrock server to the public IP.

Yet I was not able to get the same for simple voice chat.

I also fixed it so both proxy 1 and 2 work.

Proxy 2:

# sudo ss -ulnp | grep 30004
UNCONN 0      0                  *:30004            *:*    users:(("frps",pid=14712,fd=9))          
root@ChainLinkHosting-Backend-CDN:~/frp_0.68.0_linux_amd64# tcpdump -ni any udp port 30004
tcpdump: data link type LINUX_SLL2
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes
13:09:30.830105 eth0  In  IP 188.XXX.XXX.XXX.5XXXX > 62.XXX.XXX.172.30004: UDP, length 79
13:09:30.830126 eth0  Out IP 188.XXX.XXX.XXX.5XXXX > 45.XXX.XXX.XXX.30004: UDP, length 79
13:09:30.836557 eth0  In  IP 105.XXX.XXX.XXX.6XXXX > 62.XXX.XXX.172.30004: UDP, length 79

Client:

# tcpdump -ni any udp port 30004
tcpdump: data link type LINUX_SLL2
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes

Configs:

Proxy 2:

bindPort = 7000

# Specify a UDP port for KCP.
kcpBindPort = 7000

# Optional dashboard
webServer.addr = "0.0.0.0"
webServer.port = 7500
webServer.user = "admin"
webServer.password = "PASSWORD"

# IMPORTANT for UDP + MC traffic
#transport.maxPoolCount = 5000
#udpPacketSize = 1500

# Optional: Restrict allowed ports
allowPorts = [
  { single = 30004 },
  { single = 30010 },
  { single = 19131 },
  { single = 19132 }
]

# Optional security
auth.method = "token"
auth.token = "TOKEN"

Client:

# Same as the 'kcpBindPort' in frps.toml
serverPort = 7000
transport.protocol = "kcp"
#enableUdp = true

auth.method = "token"
auth.token = "TOKEN"

#[transport]

#poolCount = 5

[[proxies]]

name = "minecraft-bedrock"
type = "udp"
localIP = "45.XXX.XXX.XXX"
localPort = 19132
remotePort = 19132

# now v1 and v2 are supported
#transport.proxyProtocolVersion = "v2"

[[proxies]]

name = "voice-chat"
type = "udp"
localIP = "45.XXX.XXX.XXX"
localPort = 30004
remotePort = 30004

[[proxies]]

name = "voice-chat2"
type = "udp"
localIP = "45.XXX.XXX.XXX"
localPort = 30010
remotePort = 30010

Do you have any idea why voice chat may not be sending and passing fully to the client??

Also as well, Do you know any better config like way to pass the players raw IP and also any way to better the loading of things for players?

Thanks!

<!-- gh-comment-id:4260408108 --> @liam6080 commented on GitHub (Apr 16, 2026): Hello, As a update, I was able to get it to work by changing the bedrock server to the public IP. Yet I was not able to get the same for simple voice chat. I also fixed it so both proxy 1 and 2 work. Proxy 2: ``` # sudo ss -ulnp | grep 30004 UNCONN 0 0 *:30004 *:* users:(("frps",pid=14712,fd=9)) root@ChainLinkHosting-Backend-CDN:~/frp_0.68.0_linux_amd64# tcpdump -ni any udp port 30004 tcpdump: data link type LINUX_SLL2 tcpdump: verbose output suppressed, use -v[v]... for full protocol decode listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes 13:09:30.830105 eth0 In IP 188.XXX.XXX.XXX.5XXXX > 62.XXX.XXX.172.30004: UDP, length 79 13:09:30.830126 eth0 Out IP 188.XXX.XXX.XXX.5XXXX > 45.XXX.XXX.XXX.30004: UDP, length 79 13:09:30.836557 eth0 In IP 105.XXX.XXX.XXX.6XXXX > 62.XXX.XXX.172.30004: UDP, length 79 ``` Client: ``` # tcpdump -ni any udp port 30004 tcpdump: data link type LINUX_SLL2 tcpdump: verbose output suppressed, use -v[v]... for full protocol decode listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes ``` Configs: Proxy 2: ``` bindPort = 7000 # Specify a UDP port for KCP. kcpBindPort = 7000 # Optional dashboard webServer.addr = "0.0.0.0" webServer.port = 7500 webServer.user = "admin" webServer.password = "PASSWORD" # IMPORTANT for UDP + MC traffic #transport.maxPoolCount = 5000 #udpPacketSize = 1500 # Optional: Restrict allowed ports allowPorts = [ { single = 30004 }, { single = 30010 }, { single = 19131 }, { single = 19132 } ] # Optional security auth.method = "token" auth.token = "TOKEN" ``` Client: ``` # Same as the 'kcpBindPort' in frps.toml serverPort = 7000 transport.protocol = "kcp" #enableUdp = true auth.method = "token" auth.token = "TOKEN" #[transport] #poolCount = 5 [[proxies]] name = "minecraft-bedrock" type = "udp" localIP = "45.XXX.XXX.XXX" localPort = 19132 remotePort = 19132 # now v1 and v2 are supported #transport.proxyProtocolVersion = "v2" [[proxies]] name = "voice-chat" type = "udp" localIP = "45.XXX.XXX.XXX" localPort = 30004 remotePort = 30004 [[proxies]] name = "voice-chat2" type = "udp" localIP = "45.XXX.XXX.XXX" localPort = 30010 remotePort = 30010 ``` Do you have any idea why voice chat may not be sending and passing fully to the client?? Also as well, Do you know any better config like way to pass the players raw IP and also any way to better the loading of things for players? Thanks!
Author
Owner

@fatedier commented on GitHub (Apr 16, 2026):

Glad Bedrock is working — but I want to point out what's actually happening, because frp is not in your user traffic path.

1. Your tcpdump shows an iptables DNAT, not frp, is carrying the packets.

In  188.X.X.X.5XXXX > 62.X.X.172.30004
Out 188.X.X.X.5XXXX > 45.X.X.X.30004   (21 µs later)

The "Out" packet keeps the original player source IP and source port, only the destination IP is rewritten. frp cannot produce this: frp tunnels UDP over the work connection (KCP/TCP on 7000), it never emits raw UDP toward 45.X.X.X:30004, and it would never preserve the client's source IP as the outgoing source IP. This pattern is a classic iptables -t nat PREROUTING -p udp --dport 30004 -j DNAT --to 45.X.X.X:30004 (no SNAT). Please run on the frps host:

sudo iptables -t nat -S

That rule is intercepting packets before frps ever sees them. frps is listening on :30004 but never receives anything.

2. Why Bedrock "works" and voice-chat doesn't.

Your new client config sets localIP = "45.X.X.X" — that's frpc's own public IP. The DNAT on the frps host redirects packets to 45.X.X.X:30004 externally, so something must be listening there on the frpc machine:

  • For Bedrock you republished the container so its port is bound on the public IP → there's a listener on 45.X.X.X:19132 → it works.
  • For voice-chat the container is still published only on 172.18.0.1:30004 (docker-proxy). Nothing listens on 45.X.X.X:30004, so the DNAT'd packet is dropped.

Fix (same shape as your Bedrock fix): republish the voice-chat container without binding to 172.18.0.1, e.g. -p 30004:30004/udp instead of -p 172.18.0.1:30004:30004/udp.

3. If you actually want to use frp instead of the DNAT hack:

  • Remove the PREROUTING DNAT rules on the frps host so frps actually receives UDP.
  • In the frpc config use localIP = "172.18.0.1" (the Docker bridge), matching the original working setup for Java.
  • Leave containers bound to 172.18.0.1:<port> as they were.

4. Passing the player's real IP.

With your current DNAT path the source IP is already preserved (that's why you saw 188.X.X.X on the frpc side). If you move back to a real frp path, set transport.proxyProtocolVersion = "v2" only on proxies whose target parses PROXY protocol. Minecraft Bedrock / RakNet does not; Simple Voice Chat supports it on recent versions — check your SVC version before enabling.

5. Performance.

Nothing frp-specific will help much here. A couple of knobs:

  • Drop transport.protocol = "kcp" unless you actually have a lossy link; plain TCP is lower overhead for the control channel.
  • Or try transport.protocol = "quic" (must be set on both frps and frpc).
  • The udpPacketSize = 1500 / large maxPoolCount you set earlier are not useful for this scenario; defaults are fine.

Since the underlying problem is your iptables NAT setup, not an frp bug, I'd suggest we close this issue once voice-chat is working on your side. Happy to keep helping in the thread.

<!-- gh-comment-id:4260534561 --> @fatedier commented on GitHub (Apr 16, 2026): Glad Bedrock is working — but I want to point out what's actually happening, because **frp is not in your user traffic path**. **1. Your tcpdump shows an iptables DNAT, not frp, is carrying the packets.** ``` In 188.X.X.X.5XXXX > 62.X.X.172.30004 Out 188.X.X.X.5XXXX > 45.X.X.X.30004 (21 µs later) ``` The "Out" packet keeps the **original player source IP and source port**, only the destination IP is rewritten. frp cannot produce this: frp tunnels UDP over the work connection (KCP/TCP on 7000), it never emits raw UDP toward `45.X.X.X:30004`, and it would never preserve the client's source IP as the outgoing source IP. This pattern is a classic `iptables -t nat PREROUTING -p udp --dport 30004 -j DNAT --to 45.X.X.X:30004` (no SNAT). Please run on the frps host: ```bash sudo iptables -t nat -S ``` That rule is intercepting packets before frps ever sees them. frps is listening on `:30004` but never receives anything. **2. Why Bedrock "works" and voice-chat doesn't.** Your new client config sets `localIP = "45.X.X.X"` — that's frpc's own public IP. The DNAT on the frps host redirects packets to `45.X.X.X:30004` externally, so something must be listening there on the frpc machine: - For Bedrock you republished the container so its port is bound on the public IP → there's a listener on `45.X.X.X:19132` → it works. - For voice-chat the container is still published only on `172.18.0.1:30004` (docker-proxy). Nothing listens on `45.X.X.X:30004`, so the DNAT'd packet is dropped. Fix (same shape as your Bedrock fix): republish the voice-chat container without binding to `172.18.0.1`, e.g. `-p 30004:30004/udp` instead of `-p 172.18.0.1:30004:30004/udp`. **3. If you actually want to use frp instead of the DNAT hack:** - Remove the PREROUTING DNAT rules on the frps host so frps actually receives UDP. - In the frpc config use `localIP = "172.18.0.1"` (the Docker bridge), matching the original working setup for Java. - Leave containers bound to `172.18.0.1:<port>` as they were. **4. Passing the player's real IP.** With your current DNAT path the source IP is already preserved (that's why you saw `188.X.X.X` on the frpc side). If you move back to a real frp path, set `transport.proxyProtocolVersion = "v2"` **only on proxies whose target parses PROXY protocol**. Minecraft Bedrock / RakNet does not; Simple Voice Chat supports it on recent versions — check your SVC version before enabling. **5. Performance.** Nothing frp-specific will help much here. A couple of knobs: - Drop `transport.protocol = "kcp"` unless you actually have a lossy link; plain TCP is lower overhead for the control channel. - Or try `transport.protocol = "quic"` (must be set on both frps and frpc). - The `udpPacketSize = 1500` / large `maxPoolCount` you set earlier are not useful for this scenario; defaults are fine. Since the underlying problem is your iptables NAT setup, not an frp bug, I'd suggest we close this issue once voice-chat is working on your side. Happy to keep helping in the thread.
Author
Owner

@github-actions[bot] commented on GitHub (May 1, 2026):

Issues go stale after 14d of inactivity. Stale issues rot after an additional 3d of inactivity and eventually close.

<!-- gh-comment-id:4357240406 --> @github-actions[bot] commented on GitHub (May 1, 2026): Issues go stale after 14d of inactivity. Stale issues rot after an additional 3d of inactivity and eventually close.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: github-starred/frp#4083
No description provided.