After checking that you can open port 53 udp yourself with, say, nc (which you tried), strace the binary that tries to open port 53 and fails, and find the system call that fails. You can compare it with an strace on nc to see how it differs.
If this doesn’t clue you in (e.g., you see two attempts to listen to the same port…) Next step would be to find in the source code where it fails (look for the error message printout) and start adding diagnostic printouts before the failing system call and compile and run your edited version.
After checking that you can open port 53 udp yourself with, say, nc (which you tried), strace the binary that tries to open port 53 and fails, and find the system call that fails. You can compare it with an strace on nc to see how it differs.
If this doesn’t clue you in (e.g., you see two attempts to listen to the same port…) Next step would be to find in the source code where it fails (look for the error message printout) and start adding diagnostic printouts before the failing system call and compile and run your edited version.