从服务器上的用户运行不受信任的可执行文件的最佳方法

I'm trying to create a server that compiles and runs code submitted by the user. How can I run the executable output (compiled from code, unreliable) on the server-side, without affecting my codebase (binary executable itself)?

Is docker somehow going to be useful here? If "yes", how?

FYI, I'm using a microservices architecture. And Go for the server-side development of this service (code-runner).

The best way to run an unreliable code is isolating it, we do it a lot when reverse engineering malware. Since you are using Docker there are some precautions you would need to take that are not needed when using virtual machines.

The safest way to do it would be having another Docker container only for compiling, executing and performing any other operation needed.

Let's take the example of an application which the user sends the code and we run it for him comparing it with the expected output, as in programming contests like Codeforces.

  1. The main application receives the code
  2. The main application creates a special Docker container
  3. The main application sends the code to the special container with the file representing the expected output
  4. The special container compiles, executes and print the code output to a file and uses diff output expected_output
  5. The special container sends the diff result (basically a true or false) to the main application

This way all the stuff related to the code sent by the user is isolated so it is safer.

Some notes:

  • The container running the user code should be running it using a low privileges user for safety
  • If you need to get the output from the code back and not just a true or false from a diff then you need to be sure that his code is not generating a malware as output which you save in a file and put inside the main application server
  • Blocking libraries of threads, networking, filesystem access, etc, from the user code, helps to make it safer

[What is the] Best way to run an untrusted executable file from an user on a server?

Not at all.

Sandboxing is hard. Try using the Playground which does exactly what you need.

Or: Reimplement the playground according to your needs. https://blog.golang.org/playground Might help you get started.

Just remember to disallow dangerous packages like unsafe, runtime, os/exec and everything from net.