使用Distroless容器,安全地在tor网络中的洋葱域上发布洋葱服务

由于在tor网络上公开onion服务,需要具备强大的安全性。因此,本次我们打算利用Distroless容器在tor网络上发布一个网站。

顺便提一下,在撰写本文时我参考了 O’Reilly Docker 的资料。

太长不看

我們在這裡公開。

解释术语

Onion服务是什么意思?

Tor网络是一个用于无需审查的通信的网络,洋葱服务是一种在互联网上完全匿名的方式在Tor网络上发布网站的机制。
Tor网络经常被称为”暗网”,但由于内部举报网站和人权活动网站等可以在互联网上无需任何审查的情况下公开,因此英国公共广播公司BBC也利用onion服务在全球范围内发布新闻等内容。
例如,如果您要开发内部举报的网络系统,那么本文介绍的知识应该对您很有用。

Distroless容器是什么?

Distroless容器是基于最小必需配置创建的容器。甚至没有apt、vi、sh,甚至连busybox都没有。在gcr.io/distroless/base-nossl-debian12:latest中,主要安装的是

    CA証明書
    rootユーザの/etc/passwd

    /tmpディレクトリ
    tzdata
    glibc

这种彻底性只是说…
从安全的角度来看,没有多余的应用程序(可以防止OS命令注入等)非常理想。
gcr.io/distroless/base-nossl-debian12:latest目前只有14.79MB,非常轻量化也是一个重要的优点。
我们将以此为基础,通过多阶段构建只添加所需的文件。

实践

我們將以最簡配置來構建基礎部分。通過先進行最簡配置的試運行,我們也能理解它的運作方式等。

Docker – 只需要一个选项原生地在中文中改述:

首先创建compose.yaml文件。

version: '3.8'

services:
  nginx:
    build:
      dockerfile: ./nginx/Dockerfile
    networks:
      - tor_network
    volumes:
      - ./nginx/settings:/etc/nginx/sites-enabled:ro
      - ./htdocs:/usr/share/nginx/html:ro
    restart: unless-stopped
  tor:
    build:
      dockerfile: ./tor/Dockerfile
    networks:
      - tor_network
      - front
    volumes:
      - ./data:/var/lib/tor
      - ./tor/settings:/etc/tor
    restart: unless-stopped

networks:
  front:
  tor_network:
    internal: true

网络将提供用于连接到外部的前端网络和独立于外部且未连接到外部的内部网络tor_network。只有tor容器与外部连接,nginx容器与外部隔断,并且使用tor_network网络将tor容器和nginx容器连接在一起。

用网络图表示如下。

undefined

nginx容器和tor容器在后文的tor/Dockerfile和nginx/Dockerfile中进行了描述。

而且,两者都设定了restart:unless-stopped,如果它们关闭了就会重新启动。

T恤

在Debian 12上安装Tor,并将仅需在gcr.io/distroless/base-nossl-debian12:latest中进行操作所需的文件转移。

FROM debian:12 as build

RUN apt update && \
  apt install tor -y --no-install-recommends && \
  cp -a --parents /usr/bin/tor /opt && \
  cp -a --parents /usr/sbin/tor /opt && \
  cp -a --parents /etc/tor /opt && \
  cp -aL --parents /usr/share/tor /opt && \
  cp -a --parents /lib/x86_64-linux-gnu/libz.so.* /opt && \
  cp -a --parents /lib/x86_64-linux-gnu/libm.so.* /opt && \
  cp -a --parents /lib/x86_64-linux-gnu/libevent-2.1.so.* /opt && \
  cp -a --parents /lib/x86_64-linux-gnu/libssl.so.* /opt && \
  cp -a --parents /lib/x86_64-linux-gnu/libcrypto.so.* /opt && \
  cp -a --parents /lib/x86_64-linux-gnu/libsystemd.so.* /opt && \
  cp -a --parents /lib/x86_64-linux-gnu/liblzma.so.* /opt && \
  cp -a --parents /lib/x86_64-linux-gnu/libzstd.so.* /opt && \
  cp -a --parents /lib/x86_64-linux-gnu/libseccomp.so.* /opt && \
  cp -a --parents /lib/x86_64-linux-gnu/libcap.so.* /opt && \
  cp -a --parents /lib/x86_64-linux-gnu/libc.so.* /opt && \
  cp -a --parents /lib/x86_64-linux-gnu/libgcrypt.so.* /opt && \
  cp -a --parents /lib/x86_64-linux-gnu/liblz4.so.* /opt && \
  cp -a --parents /lib/x86_64-linux-gnu/libgpg-error.so.* /opt

FROM gcr.io/distroless/base-nossl-debian12:latest
COPY --from=build /opt /

ENTRYPOINT  ["/usr/bin/tor"]

在tor的配置文件torrc中,将连接指向80端口的请求转发给nginx容器。
※在Docker网络中,可以通过容器名称进行名称解析。

SocksPort 0
HiddenServiceDir /var/lib/tor/hidden_service/
HiddenServicePort 80 nginx:80

为了防止成为别人的垫脚石,我进行了SocksPort 0的设置。

Nginx的释义。

我在debian:12上安装了nginx,并将其所需的文件移动到gcr.io/distroless/base-nossl-debian12:latest。

FROM debian:12 as build

RUN apt update && \
  apt install nginx -y --no-install-recommends && \
  cp -a --parents /usr/share/nginx /opt && \
  cp -a --parents /var/log/nginx /opt && \
  cp -a --parents /var/lib/nginx /opt && \
  cp -aL --parents /var/run /opt && \
  cp -a --parents /etc/nginx /opt && \
  cp -a --parents /etc/passwd /opt && \
  cp -a --parents /etc/group /opt && \
  cp -a --parents /usr/sbin/nginx /opt && \
  cp -a --parents /lib/x86_64-linux-gnu/libcrypt.so.* /opt && \
  cp -a --parents /lib/x86_64-linux-gnu/libpcre2-8.so.* /opt && \
  cp -a --parents /lib/x86_64-linux-gnu/libssl.so.* /opt && \
  cp -a --parents /lib/x86_64-linux-gnu/libcrypto.so.* /opt && \
  cp -a --parents /lib/x86_64-linux-gnu/libz.so.* /opt && \
  cp -a --parents /lib/x86_64-linux-gnu/libc.so.* /opt

FROM gcr.io/distroless/base-nossl-debian12:latest
COPY --from=build /opt /

EXPOSE 80

ENTRYPOINT ["/usr/sbin/nginx", "-g", "daemon off;"]

将nginx的配置文件放置。

server {
    listen       80;
    listen  [::]:80;
    server_name  localhost;

    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}

由於無法確定是否運作中,我將放置index.html以用於顯示。

<!DOCTYPE html>
<html>
  <head>
    <title>docker hidden service test title</title>
  </head>
  <body>
    <div>docker hidden service test body div</div>
  </body>
</html>

以上的最小構成已經完成。

启动

在中文中为”Docker通常通过使用docker-compose up -d命令进行启动”

确认启动(与洋葱网络服务的连接确认)。

当正常启动时,会在data/hidden_service/hostname文件中输出以下内容。

dbutwdcq576d6p5435sbhnbbl3lafi6stfyu3xgt6v6eitenbefnolid.onion

请使用Tor浏览器连接到该地址,并确认已显示创建的index.html文件。

docker hidden service test title — Tor Browser 2023_09_10 15_11_22.png

我确认事情在顺利进行。

通过使用Distroless,您可以轻松地启动一个非常安全的服务!如果您需要高安全性,一定要使用Distroless!

bannerAds