如何创建用于执行不可信代码的Golang沙箱环境
如何创建用于执行不可信代码的Golang沙箱环境 你好,
我对创建一个Go沙箱很感兴趣,用于执行通过curl传递的任意、不受信任的Go代码。
我相信最著名的此类沙箱是 https://play.golang.org/
我找到了存放此代码的GitHub仓库(https://github.com/golang/playground),并且正在尝试运行他们在仓库中提供的示例。
GitHub上的README似乎表明我可以通过Docker镜像 + curl来执行任意代码。
以下是README中的示例:
docker build -t golang/playground .
docker run -d --name=play --rm -p 8080:8080 golang/playground
# 运行一些Go代码
cat /path/to/hello_world.go | go run client.go | curl -s --upload-file - localhost:8080/compile
虽然这看起来很简单,但它并没有正常工作。
问题似乎出在一个“SANDBOX_BACKEND_URL”环境变量上。
错误信息:
#Golang Error
cmdFunc error: POST "http://sandbox_dev.sandnet/run": Post "http://sandbox_dev.sandnet/run": dial tcp: lookup sandbox_dev.sandnet on 127.0.0.11:53: no such host
#http/mux Error
2020/10/17 20:39:26 http: panic serving 172.17.0.1:60486:
no SANDBOX_BACKEND_URL environment and no default defined for project ""
有人能帮我理解这个错误并帮助我执行示例中的代码吗?
更多关于如何创建用于执行不可信代码的Golang沙箱环境的实战教程也可以访问 https://www.itying.com/category-94-b0.html
截至目前我所尝试的方法:
Github 仓库中有一个 Makefile,其中包含一些用于运行 Docker 化环境的步骤。
Makefile 的相关内容如下:
runlocal:
docker network create sandnet || true
docker kill play_dev || true
docker run --name=play_dev --rm --network=sandnet -ti -p 127.0.0.1:8081:8080/tcp golang/
playground --backend-url="http://sandbox_dev.sandnet/run"
当我创建 Docker 网络并使用设置的 --backend-url 运行容器时,遇到了同样的问题。
更多关于如何创建用于执行不可信代码的Golang沙箱环境的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
这是一个典型的沙箱环境配置问题。错误表明沙箱后端服务没有正确配置。
问题分析
SANDBOX_BACKEND_URL 环境变量用于指定实际执行代码的沙箱后端服务地址。在 playground 架构中,前端接收编译请求,然后转发到后端沙箱环境执行。
解决方案
1. 完整部署方案
你需要同时启动前端和后端服务:
# 克隆仓库
git clone https://github.com/golang/playground.git
cd playground
# 构建并启动后端沙箱
cd sandbox
docker build -t go-sandbox .
docker run -d --name sandbox-backend -p 8081:8081 go-sandbox
# 构建并启动前端服务(设置正确的后端URL)
cd ..
docker build -t playground-frontend .
docker run -d --name playground \
-p 8080:8080 \
-e SANDBOX_BACKEND_URL=http://host.docker.internal:8081 \
playground-frontend
2. 使用 Docker Compose(推荐)
创建 docker-compose.yml:
version: '3'
services:
sandbox:
build: ./sandbox
container_name: sandbox-backend
ports:
- "8081:8081"
networks:
- playground-net
frontend:
build: .
container_name: playground-frontend
ports:
- "8080:8080"
environment:
- SANDBOX_BACKEND_URL=http://sandbox:8081
depends_on:
- sandbox
networks:
- playground-net
networks:
playground-net:
driver: bridge
然后运行:
docker-compose up -d
3. 测试代码执行
创建测试文件 hello.go:
package main
import "fmt"
func main() {
fmt.Println("Hello from sandbox!")
}
执行代码:
cat hello.go | go run client.go | curl -s --upload-file - http://localhost:8080/compile
4. 直接使用 client.go 的示例
查看 client.go 的用法:
// client.go 使用示例
package main
import (
"fmt"
"io"
"net/http"
"os"
)
func main() {
if len(os.Args) < 2 {
fmt.Println("Usage: go run client.go <filename.go>")
return
}
file, err := os.Open(os.Args[1])
if err != nil {
panic(err)
}
defer file.Close()
resp, err := http.Post("http://localhost:8080/compile",
"application/x-www-form-urlencoded", file)
if err != nil {
panic(err)
}
defer resp.Body.Close()
io.Copy(os.Stdout, resp.Body)
}
运行:
go run client.go hello.go
关键配置说明
- SANDBOX_BACKEND_URL: 必须指向实际运行代码的沙箱容器
- 网络配置: 确保前端容器能访问后端容器(使用 Docker 网络或 host.docker.internal)
- 端口映射: 前端 8080 对外,后端 8081 供内部通信
如果使用 Linux,可能需要修改 host.docker.internal 为实际的容器 IP 或使用 Docker 网络别名。

