중계기 운영자

  • 우분투 저장소의 패키지를 사용하지 마세요. 패키지로는 안정적인 업데이트가 불가능해요. 즉 우분투 저장소를 사용하면 중요한 안정성과 보안 패치를 놓칠 수 있다는 거예요.
  • 다음 명령을 실행하여 우분투 버전을 확인하세요:
     ‪$ lsb_release -c
    
  • 루트 계정 상태에서 to /etc/apt/sources.list. Replace 'version' 에 다음 행을 추가하세요. 이때 버전은 이전 단계에서 확인한 버전을 적으세요:
     deb https://deb.torproject.org/torproject.org version main
     deb-src https://deb.torproject.org/torproject.org version main
    
  • 다음 명령을 실행하여 패키지 서명에 사용 된 gpg키를 추가하세요:
     ‪$ curl https://deb.torproject.org/torproject.org/A3C4F0F979CAA22CDBA8F512EE8CBC9E886DDD89.asc | sudo apt-key add -
    
  • Tor를 설치하고 서명을 확인하려면 다음 명령을 실행하세요:
     ‪$ sudo apt-get update
     ‪$ sudo apt-get install tor deb.torproject.org-keyring
    

Tor는 동적 IP 주소로 중계기를 무난하게 다룰 수 있어요. torrc의 주소 줄을 공란으로 두시면 Tor가 알아맞힐게요.

아니에요. 법 집행기관이 출구 노드에 관심을 갖게 되면, 컴퓨터가 압류당할 수 있어요 이런 까닭에, 출구 중계기를 집에서 혹은 가정 내 인터넷 접속을 통해 실행하지 않는 게 가장 좋어요.

집에서 돌리는 대신에, Tor에 호의적인 상업 시설에서 출구 중계기를 돌리는 걸 고려해 보세요. 출구 중계기를 위한 별도의 IP 주소를 할당받고, 이 주소를 통해 자체 트래픽을 라우팅하지 마세요. 출구 중계기로 호스팅 중인 컴퓨터에 민감한 개인 정보를 저장해두는 것도 당연히 피하셔야 해요.

Tor 중계기에서 예상한 것보다 더 많은 메모리를 사용할 경우, 그 점유하는 양을 줄이기 위해 다음과 같은 방법을 써볼 수 있어요:

  • Linux 사용자라면, glibc에서 malloc의 실행(implementation) 중 메모리 파편화(memory fragmentation)버그가 발생할 수 있어요. 이때 메모리 파편화란, Tor가 시스템에 메모리를 보낼 때, 메모리 조각이 파편화돼 재사용이 어렵게 되는 현상을 말해요. Tor의 tar 파일(tarball)엔 OpenBSD의 malloc implementation이 기본적으로 포함돼있어요. 파편화 버그가 glibc 대비 많지 않아요(그 반대급부로 CPU 부하량이 높어요). OpenBSD 에서의 'malloc implementation'을 glibc 대신 사용하도록 Tor를 설정할 수 있어요:./configure --enable-openbsd-malloc.
  • 운영하는 중계기의 속도가 빠를 경우, 즉 TLS 접속을 많이 개방(open)해둘 수 있다면, OpenSSL's internal buffer로 인해 많은 메모리를 잃을 수 있어요(소켓 당 38KB 이상). Tor 프로젝트에선 OpenSSL 방식에서 미사용 버퍼의 메모리를 더 적극적으로 방출하도록 패치를 진행했어요. OpenSSL의 버전을 1.0.0 이상으로 업데이트하면, Tor의 빌드 프로세스에서 자동적으로 이를 감지해 패치된 기능을 활성화해요.
  • 위와 같은 조처에도 불구하고 메모리 부하 관련 문제를 해결할 수 없다면, 중계기의 공시 대역폭량을 줄이세요. 대역폭의 공시량이 적을 수록, 다른 사용자들의 유입량이 적어집니다. 따라서 중계기의 성장세가 꺽이게 돼요. 매뉴얼 페이지에 기재된 MaxAdvertisedBandwidth 옵션 항목을 참고하세요.

앞서 말씀드린 바와 같이, Tor 중계기는 많은 램을 사용해요. 그러나 아무리 빠른 출구 중계기라 하더라도 메모리 사용량이 500-1000 MB인 것은 흔하지 않아요.

귀하가 출구 접속을 허용할 경우, 중계기를 통해 사람들이 접속하는 몇몇 서비스에서 정보를 수집하기 위해 접속을 역추적해요. 예를 들어, IRC 서버에서 identd 포트로 역으로 접속해 어떤 사용자가 접속했는지를 기록해요(Tor에서 사용자 정보를 알 수 없으므로, IRC 서버에서 시도한 해당 방식은 유효하지 않아요만, 아무튼 시도는 해요). 또한 중계기를 거쳐 나가는 사용자는 IRC 서버, 웹사이트와 같은 곳에 있는 사용자의 관심을 끌게 돼요. 그들을 중계해온 호스트가 누군자 알고 싶어 하기 때문이에요.

다른 이유는 인터넷에서 개방 프록시를 스캔하는 집단이 Tor 중계기가 가끔 socks 포트를 대외적으로 노출시킨다는 걸 파악했기 때문이에요. Tor 프로젝트에선 socks 포트를 근거리 통신망에서만 바인딩 해두길 권장해요.

어떤 경우든, 보안과 관계된 모든 요소를 최신으로 유지하셔야 해요. Tor 중계기의 보안에서 보안 관련 더 자세한 지침을 살펴보세요.

아주 좋아요. Tor 프로젝트에서 '출구 정책'을 시행하는 이유가 여기에 있어요.

Tor 중계기 각각에는 출구 정책이 적용돼요. 출구 정책이란 주어진 중계기에서 어떤 아웃바운드 트래픽(outbound connections)을 허용하고 거부할지 규정하는 정책을 말해요. '출구 정책'은 저장소를 통해 Tor 클라이언트에게 전달돼요. 따라서 클라이언트는 원 목적지로의 전송을 거부하는 출구 중계기를 고르는 걸 자동으로 피할 수 있어요. 이런 방식으로 각 중계기는 접속하고자 하는 서비스, 호스트, 네트워크를 선택할 수 있어요. 이때 남용 가능성과 각 중계기의 상황이 고려돼요. '출구 정책'을 초기 설정대로 사용하고 있을 경우 진입 노드에서 발생한 문제 해결 지원 를 참고하세요. 그리고 Mike Perry가 작성한 성가신 문제에 최대한 얽히지 않으면서 출구 노드를 운영하는 방법 문서도 읽어보세요.

초기 설정 상 '출구 정책'은 (웹 브라우징과 같은) 대중적인 서비스로의 접속을 허용하는 한편, (메일과 같이) 남용 가능성이 있는 몇몇 서비스를 제한해요. 또한 (Tor 기본 파일 공유 포트와 같이) Tor가 감당할 수 없는 부하량이 오가는 서비스 또한 제한돼요. torrc 파일을 수정해서 출구 정책을 변경할 수 있어요. 남용될 가능성이 있는 서비스 대다수를 피하고자 한다면, torrc 파일 내 설정을 "reject *:*"로 변경하세요. 해당 설정으로 변경 시 중계기는 Tor 네트워크 내 트래픽을 중계하는 데 사용되지만, 외부 웹사이트나 다른 서비스를 접속하는 데에는 사용되지 않게 돼요.

출구 접속을 허용할 때에는 '이름 분석'이 유효한지 확인하세요(즉 컴퓨터에서 인터넷 주소를 올바르게 분해했는지를 확인하세요). (모든 트래픽을 차단하는 방화벽이나 콘텐츠 필터 등에 의해) 주어진 자원이 컴퓨터에 전송될 수 없는 경우, '출구 정책'에서 해당 자원을 단호히 거부하세요. 그러지 않으면 Tor 사용자에게도 영향이 갑니다.

Tor 프로젝트는 꽤 안정적인 인터넷 접속을 가진 분들을 찾고 있어요. 즉 적어도 10 Mbit/s (Mbps) 가량의 대역폭을 문제 없이 낼 수 있는 환경이어야 해요. 환경이 이에 부합한다면, Tor 중계기를 운영해보시는 건 어떨까요?

설사 최소 10 Mbit/s의 대역폭을 이용할 수 있는 환경이 아니더라도, 대역폭에서 최소 1 MBit/s 을 낼 수 있다면 obfs4 Tor 브리지를 운영해 Tor에 도움을 주실 수 있어요.

Tor는 주어진 컴퓨터에 호스트네임을 요청한 후 받은 호스트네임을 분해하는 방식으로 IP 주소를 추정해요. 일반적인 사용자의 컴퓨터 내 their /etc/hosts 파일엔 옛 IP 주소가 입력돼있어요.

If that doesn't fix it, you should use the "Address" config option to specify the IP address you want it to pick. If your computer is behind a NAT and it only has an internal IP address, see the following Support entry on dynamic IP addresses.

한편 IP 주소가 많을 경우, 'OutboundBindAddress'을 설정해 외부에 표시하고자 하는 IP 주소로 외부 접속을 받고자 할 수 있어요.

Tor는 IPv6를 부분적으로만 지원하며, IPv6 접속이 가능할 경우 각 중계기 운영자가 중계기 내 torrc 설정 파일에 IPv6 기능을 활성화할 것을 권장해요. 당분간 Tor는 중계기에 IPv4 주소를 요구할 거예요. 해당 기간 동안 IPv6 주소만 취급하는 호스트로 Tor 중계기를 운영할 수 없어요.

중계기를 비교적 새로 만드셨다면 좀 더 기다려보세요. Tor는 '대역폭 검증'에서 보낸 자료를 기반으로 한 휴리스틱 방식으로 사용할 중계기를 선택해요. '대역폭 검증'은 귀하측 중계기의 처리능력을 측정하며, 중계기의 트래픽 부하수준을 최적으로 조정하는 역할을 담당해요. 중계기가 새로 설정되고 안정화되기까지의 전개과정(lifecycle)을 다음 블로그 포스트에서 상세하게 다루었으니, 관심있으시면 확인해보세요. 중계기의 운영 기간이 꽤 됐는데도 문제를 겪고 있다면, tor-relays 목록에 문의해주세요.

If you're using Debian or Ubuntu especially, please use the Tor Project's repository, so you can easily receive updates. In addition, using the package provides other conveniences:

  • Your ulimit -n gets set to a high number, so Tor can keep open all the connections it needs.
  • The package creates and uses a separate user, so you don't need to run Tor as your own user.
  • The package includes an init script so Tor runs at boot.
  • Tor can bind to low-numbered ports, then drop privileges.

Windows에서 중계기를 운영하려면 다음 지침을 따르세요:

하루종일(24/7) 켜둘 수 있는 경우에만 Windows 중계기를 운영할 수 있어요 상시 켜둘 수 있을지 확신이 안 든다면, Snowflake가 Tor 네트워크에 자원을 기여하는 더 좋은 방법이에요.

On relay search we show an amber dot next to the relay nickname when it is overloaded. 중계기가 과부하됐다는 건 한 개 이상의 부하 메트릭스에 트리거가 걸렸다는 걸 뜻해요.

중계기의 과부하가 발생하고 복구된 후, 약 72시간 동안 Tor측에서 중계기가 과부하에 걸렸음을 안내해요.

중계기가 과부하되었다면 다음과 같이 하세요:

  1. https://status.torproject.org/ 에 들어간 후, "Tor network" 카테고리 내에 보고된 이슈가 있었는지 점검하세요.

  2. 네트워크, 메모리, CPU 부하 측면에서 시스템의 sysctl을 조정해보는 걸고려해보세요.

  3. 상황을 잘 파악할 수 있도록 MetricsPort를 활성화하는 걸 고려해보세요.

네트워크, 메모리, CPU 부하 측면에서 sysctl 의 조정

TCP 포트 고갈

TCP 포트 고갈 문제를 겪고 있다면, 로컬 포트 범위를 확장하는 걸 고려하세요. 다음을 통해 로컬 포트 범위를 확장할 수 있어요:

# sysctl -w net.ipv4.ip_local_port_range="15000 64000"

또는

# echo 15000 64000 > /proc/sys/net/ipv4/ip_local_port_range

Keep in mind that tuning sysctl as described is not permanent and will be lost upon restart. You need to add the configuration to /etc/sysctl.conf or to a file in /etc/sysctl.d/ to make it permanent.

MetricsPort

To understand the well-being of Tor relays and the Tor network it is vital to provide and have access to relay metrics. Relay overload information has been added to relay descriptors since 0.4.6+ but it was not until Tor >= 0.4.7.1-alpha that an interface to the underlying relay metrics was available: the metrics port.

MetricsPort를 활성화하기

Tor provides access to the metrics port via a torrc configuration option called MetricsPort.

It's important to understand that exposing the tor MetricsPort publicly is dangerous for the Tor network users, which is why that port is not enabled by default and its access has to be governed by an access policy. 이 포트를 열기 전 사전 준비를 철저하게 하세요. 디버깅이 끝나는 대로 바로 포트를 닫으셔야 해요.

Let's assume you are the only user on a server that runs a Tor relay. You can enable the metrics port adding this to your torrc file:

MetricsPort 127.0.0.1:9035
MetricsPortPolicy accept 127.0.0.1

And then you will be able to easily retrieve the metrics with:

# curl http://127.0.0.1:9035/metrics

초기 설정 상 Prometheus 포맷이 기본으로 설정돼있어요.

Note: every user on that server will be able to access those relay metrics in the example above. In general, set a very strict access policy with MetricsPortPolicy and consider using your operating systems firewall features for defense in depth.

For a more detailed explanation about MetricsPort and MetricsPortPolicy see tor's man page.

MetricsPort output

Here is an example of what output enabling MetricsPort will produce (we omitted any congestion control related metrics as we still need to stabilize that interface):

# HELP tor_relay_connections Total number of opened connections
# TYPE tor_relay_connections gauge
tor_relay_connections{type="OR listener",direction="initiated",state="opened",family="ipv4"} 0
tor_relay_connections{type="OR listener",direction="initiated",state="opened",family="ipv6"} 0
tor_relay_connections{type="OR listener",direction="received",state="opened",family="ipv4"} 0
tor_relay_connections{type="OR listener",direction="received",state="opened",family="ipv6"} 0
tor_relay_connections{type="OR",direction="initiated",state="opened",family="ipv4"} 0
tor_relay_connections{type="OR",direction="initiated",state="opened",family="ipv6"} 0
tor_relay_connections{type="OR",direction="received",state="opened",family="ipv4"} 0
tor_relay_connections{type="OR",direction="received",state="opened",family="ipv6"} 0
tor_relay_connections{type="Exit",direction="initiated",state="opened",family="ipv4"} 0
tor_relay_connections{type="Exit",direction="initiated",state="opened",family="ipv6"} 0
tor_relay_connections{type="Exit",direction="received",state="opened",family="ipv4"} 0
tor_relay_connections{type="Exit",direction="received",state="opened",family="ipv6"} 0
tor_relay_connections{type="Socks listener",direction="initiated",state="opened",family="ipv4"} 0
tor_relay_connections{type="Socks listener",direction="initiated",state="opened",family="ipv6"} 0
tor_relay_connections{type="Socks listener",direction="received",state="opened",family="ipv4"} 0
tor_relay_connections{type="Socks listener",direction="received",state="opened",family="ipv6"} 0
tor_relay_connections{type="Socks",direction="initiated",state="opened",family="ipv4"} 0
tor_relay_connections{type="Socks",direction="initiated",state="opened",family="ipv6"} 0
tor_relay_connections{type="Socks",direction="received",state="opened",family="ipv4"} 0
tor_relay_connections{type="Socks",direction="received",state="opened",family="ipv6"} 0
tor_relay_connections{type="Directory listener",direction="initiated",state="opened",family="ipv4"} 0
tor_relay_connections{type="Directory listener",direction="initiated",state="opened",family="ipv6"} 0
tor_relay_connections{type="Directory listener",direction="received",state="opened",family="ipv4"} 0
tor_relay_connections{type="Directory listener",direction="received",state="opened",family="ipv6"} 0
tor_relay_connections{type="Directory",direction="initiated",state="opened",family="ipv4"} 0
tor_relay_connections{type="Directory",direction="initiated",state="opened",family="ipv6"} 0
tor_relay_connections{type="Directory",direction="received",state="opened",family="ipv4"} 0
tor_relay_connections{type="Directory",direction="received",state="opened",family="ipv6"} 0
tor_relay_connections{type="Control listener",direction="initiated",state="opened",family="ipv4"} 0
tor_relay_connections{type="Control listener",direction="initiated",state="opened",family="ipv6"} 0
tor_relay_connections{type="Control listener",direction="received",state="opened",family="ipv4"} 0
tor_relay_connections{type="Control listener",direction="received",state="opened",family="ipv6"} 0
tor_relay_connections{type="Control",direction="initiated",state="opened",family="ipv4"} 0
tor_relay_connections{type="Control",direction="initiated",state="opened",family="ipv6"} 0
tor_relay_connections{type="Control",direction="received",state="opened",family="ipv4"} 0
tor_relay_connections{type="Control",direction="received",state="opened",family="ipv6"} 0
tor_relay_connections{type="Transparent pf/netfilter listener",direction="initiated",state="opened",family="ipv4"} 0
tor_relay_connections{type="Transparent pf/netfilter listener",direction="initiated",state="opened",family="ipv6"} 0
tor_relay_connections{type="Transparent pf/netfilter listener",direction="received",state="opened",family="ipv4"} 0
tor_relay_connections{type="Transparent pf/netfilter listener",direction="received",state="opened",family="ipv6"} 0
tor_relay_connections{type="Transparent natd listener",direction="initiated",state="opened",family="ipv4"} 0
tor_relay_connections{type="Transparent natd listener",direction="initiated",state="opened",family="ipv6"} 0
tor_relay_connections{type="Transparent natd listener",direction="received",state="opened",family="ipv4"} 0
tor_relay_connections{type="Transparent natd listener",direction="received",state="opened",family="ipv6"} 0
tor_relay_connections{type="DNS listener",direction="initiated",state="opened",family="ipv4"} 0
tor_relay_connections{type="DNS listener",direction="initiated",state="opened",family="ipv6"} 0
tor_relay_connections{type="DNS listener",direction="received",state="opened",family="ipv4"} 0
tor_relay_connections{type="DNS listener",direction="received",state="opened",family="ipv6"} 0
tor_relay_connections{type="Extended OR",direction="initiated",state="opened",family="ipv4"} 0
tor_relay_connections{type="Extended OR",direction="initiated",state="opened",family="ipv6"} 0
tor_relay_connections{type="Extended OR",direction="received",state="opened",family="ipv4"} 0
tor_relay_connections{type="Extended OR",direction="received",state="opened",family="ipv6"} 0
tor_relay_connections{type="Extended OR listener",direction="initiated",state="opened",family="ipv4"} 0
tor_relay_connections{type="Extended OR listener",direction="initiated",state="opened",family="ipv6"} 0
tor_relay_connections{type="Extended OR listener",direction="received",state="opened",family="ipv4"} 0
tor_relay_connections{type="Extended OR listener",direction="received",state="opened",family="ipv6"} 0
tor_relay_connections{type="HTTP tunnel listener",direction="initiated",state="opened",family="ipv4"} 0
tor_relay_connections{type="HTTP tunnel listener",direction="initiated",state="opened",family="ipv6"} 0
tor_relay_connections{type="HTTP tunnel listener",direction="received",state="opened",family="ipv4"} 0
tor_relay_connections{type="HTTP tunnel listener",direction="received",state="opened",family="ipv6"} 0
tor_relay_connections{type="Metrics listener",direction="initiated",state="opened",family="ipv4"} 0
tor_relay_connections{type="Metrics listener",direction="initiated",state="opened",family="ipv6"} 0
tor_relay_connections{type="Metrics listener",direction="received",state="opened",family="ipv4"} 0
tor_relay_connections{type="Metrics listener",direction="received",state="opened",family="ipv6"} 0
tor_relay_connections{type="Metrics",direction="initiated",state="opened",family="ipv4"} 0
tor_relay_connections{type="Metrics",direction="initiated",state="opened",family="ipv6"} 0
tor_relay_connections{type="Metrics",direction="received",state="opened",family="ipv4"} 0
tor_relay_connections{type="Metrics",direction="received",state="opened",family="ipv6"} 0
# HELP tor_relay_connections_total Total number of created/rejected connections
# TYPE tor_relay_connections_total counter
tor_relay_connections_total{type="OR listener",direction="initiated",state="created",family="ipv4"} 0
tor_relay_connections_total{type="OR listener",direction="initiated",state="created",family="ipv6"} 0
tor_relay_connections_total{type="OR listener",direction="received",state="created",family="ipv4"} 0
tor_relay_connections_total{type="OR listener",direction="received",state="created",family="ipv6"} 0
tor_relay_connections_total{type="OR listener",direction="received",state="rejected",family="ipv4"} 0
tor_relay_connections_total{type="OR listener",direction="received",state="rejected",family="ipv6"} 0
tor_relay_connections_total{type="OR",direction="initiated",state="created",family="ipv4"} 0
tor_relay_connections_total{type="OR",direction="initiated",state="created",family="ipv6"} 0
tor_relay_connections_total{type="OR",direction="received",state="created",family="ipv4"} 0
tor_relay_connections_total{type="OR",direction="received",state="created",family="ipv6"} 0
tor_relay_connections_total{type="OR",direction="received",state="rejected",family="ipv4"} 0
tor_relay_connections_total{type="OR",direction="received",state="rejected",family="ipv6"} 0
tor_relay_connections_total{type="Exit",direction="initiated",state="created",family="ipv4"} 0
tor_relay_connections_total{type="Exit",direction="initiated",state="created",family="ipv6"} 0
tor_relay_connections_total{type="Exit",direction="received",state="created",family="ipv4"} 0
tor_relay_connections_total{type="Exit",direction="received",state="created",family="ipv6"} 0
tor_relay_connections_total{type="Exit",direction="received",state="rejected",family="ipv4"} 0
tor_relay_connections_total{type="Exit",direction="received",state="rejected",family="ipv6"} 0
tor_relay_connections_total{type="Socks listener",direction="initiated",state="created",family="ipv4"} 0
tor_relay_connections_total{type="Socks listener",direction="initiated",state="created",family="ipv6"} 0
tor_relay_connections_total{type="Socks listener",direction="received",state="created",family="ipv4"} 0
tor_relay_connections_total{type="Socks listener",direction="received",state="created",family="ipv6"} 0
tor_relay_connections_total{type="Socks listener",direction="received",state="rejected",family="ipv4"} 0
tor_relay_connections_total{type="Socks listener",direction="received",state="rejected",family="ipv6"} 0
tor_relay_connections_total{type="Socks",direction="initiated",state="created",family="ipv4"} 0
tor_relay_connections_total{type="Socks",direction="initiated",state="created",family="ipv6"} 0
tor_relay_connections_total{type="Socks",direction="received",state="created",family="ipv4"} 0
tor_relay_connections_total{type="Socks",direction="received",state="created",family="ipv6"} 0
tor_relay_connections_total{type="Socks",direction="received",state="rejected",family="ipv4"} 0
tor_relay_connections_total{type="Socks",direction="received",state="rejected",family="ipv6"} 0
tor_relay_connections_total{type="Directory listener",direction="initiated",state="created",family="ipv4"} 0
tor_relay_connections_total{type="Directory listener",direction="initiated",state="created",family="ipv6"} 0
tor_relay_connections_total{type="Directory listener",direction="received",state="created",family="ipv4"} 0
tor_relay_connections_total{type="Directory listener",direction="received",state="created",family="ipv6"} 0
tor_relay_connections_total{type="Directory listener",direction="received",state="rejected",family="ipv4"} 0
tor_relay_connections_total{type="Directory listener",direction="received",state="rejected",family="ipv6"} 0
tor_relay_connections_total{type="Directory",direction="initiated",state="created",family="ipv4"} 0
tor_relay_connections_total{type="Directory",direction="initiated",state="created",family="ipv6"} 0
tor_relay_connections_total{type="Directory",direction="received",state="created",family="ipv4"} 0
tor_relay_connections_total{type="Directory",direction="received",state="created",family="ipv6"} 0
tor_relay_connections_total{type="Directory",direction="received",state="rejected",family="ipv4"} 0
tor_relay_connections_total{type="Directory",direction="received",state="rejected",family="ipv6"} 0
tor_relay_connections_total{type="Control listener",direction="initiated",state="created",family="ipv4"} 0
tor_relay_connections_total{type="Control listener",direction="initiated",state="created",family="ipv6"} 0
tor_relay_connections_total{type="Control listener",direction="received",state="created",family="ipv4"} 0
tor_relay_connections_total{type="Control listener",direction="received",state="created",family="ipv6"} 0
tor_relay_connections_total{type="Control listener",direction="received",state="rejected",family="ipv4"} 0
tor_relay_connections_total{type="Control listener",direction="received",state="rejected",family="ipv6"} 0
tor_relay_connections_total{type="Control",direction="initiated",state="created",family="ipv4"} 0
tor_relay_connections_total{type="Control",direction="initiated",state="created",family="ipv6"} 0
tor_relay_connections_total{type="Control",direction="received",state="created",family="ipv4"} 0
tor_relay_connections_total{type="Control",direction="received",state="created",family="ipv6"} 0
tor_relay_connections_total{type="Control",direction="received",state="rejected",family="ipv4"} 0
tor_relay_connections_total{type="Control",direction="received",state="rejected",family="ipv6"} 0
tor_relay_connections_total{type="Transparent pf/netfilter listener",direction="initiated",state="created",family="ipv4"} 0
tor_relay_connections_total{type="Transparent pf/netfilter listener",direction="initiated",state="created",family="ipv6"} 0
tor_relay_connections_total{type="Transparent pf/netfilter listener",direction="received",state="created",family="ipv4"} 0
tor_relay_connections_total{type="Transparent pf/netfilter listener",direction="received",state="created",family="ipv6"} 0
tor_relay_connections_total{type="Transparent pf/netfilter listener",direction="received",state="rejected",family="ipv4"} 0
tor_relay_connections_total{type="Transparent pf/netfilter listener",direction="received",state="rejected",family="ipv6"} 0
tor_relay_connections_total{type="Transparent natd listener",direction="initiated",state="created",family="ipv4"} 0
tor_relay_connections_total{type="Transparent natd listener",direction="initiated",state="created",family="ipv6"} 0
tor_relay_connections_total{type="Transparent natd listener",direction="received",state="created",family="ipv4"} 0
tor_relay_connections_total{type="Transparent natd listener",direction="received",state="created",family="ipv6"} 0
tor_relay_connections_total{type="Transparent natd listener",direction="received",state="rejected",family="ipv4"} 0
tor_relay_connections_total{type="Transparent natd listener",direction="received",state="rejected",family="ipv6"} 0
tor_relay_connections_total{type="DNS listener",direction="initiated",state="created",family="ipv4"} 0
tor_relay_connections_total{type="DNS listener",direction="initiated",state="created",family="ipv6"} 0
tor_relay_connections_total{type="DNS listener",direction="received",state="created",family="ipv4"} 0
tor_relay_connections_total{type="DNS listener",direction="received",state="created",family="ipv6"} 0
tor_relay_connections_total{type="DNS listener",direction="received",state="rejected",family="ipv4"} 0
tor_relay_connections_total{type="DNS listener",direction="received",state="rejected",family="ipv6"} 0
tor_relay_connections_total{type="Extended OR",direction="initiated",state="created",family="ipv4"} 0
tor_relay_connections_total{type="Extended OR",direction="initiated",state="created",family="ipv6"} 0
tor_relay_connections_total{type="Extended OR",direction="received",state="created",family="ipv4"} 0
tor_relay_connections_total{type="Extended OR",direction="received",state="created",family="ipv6"} 0
tor_relay_connections_total{type="Extended OR",direction="received",state="rejected",family="ipv4"} 0
tor_relay_connections_total{type="Extended OR",direction="received",state="rejected",family="ipv6"} 0
tor_relay_connections_total{type="Extended OR listener",direction="initiated",state="created",family="ipv4"} 0
tor_relay_connections_total{type="Extended OR listener",direction="initiated",state="created",family="ipv6"} 0
tor_relay_connections_total{type="Extended OR listener",direction="received",state="created",family="ipv4"} 0
tor_relay_connections_total{type="Extended OR listener",direction="received",state="created",family="ipv6"} 0
tor_relay_connections_total{type="Extended OR listener",direction="received",state="rejected",family="ipv4"} 0
tor_relay_connections_total{type="Extended OR listener",direction="received",state="rejected",family="ipv6"} 0
tor_relay_connections_total{type="HTTP tunnel listener",direction="initiated",state="created",family="ipv4"} 0
tor_relay_connections_total{type="HTTP tunnel listener",direction="initiated",state="created",family="ipv6"} 0
tor_relay_connections_total{type="HTTP tunnel listener",direction="received",state="created",family="ipv4"} 0
tor_relay_connections_total{type="HTTP tunnel listener",direction="received",state="created",family="ipv6"} 0
tor_relay_connections_total{type="HTTP tunnel listener",direction="received",state="rejected",family="ipv4"} 0
tor_relay_connections_total{type="HTTP tunnel listener",direction="received",state="rejected",family="ipv6"} 0
tor_relay_connections_total{type="Metrics listener",direction="initiated",state="created",family="ipv4"} 0
tor_relay_connections_total{type="Metrics listener",direction="initiated",state="created",family="ipv6"} 0
tor_relay_connections_total{type="Metrics listener",direction="received",state="created",family="ipv4"} 0
tor_relay_connections_total{type="Metrics listener",direction="received",state="created",family="ipv6"} 0
tor_relay_connections_total{type="Metrics listener",direction="received",state="rejected",family="ipv4"} 0
tor_relay_connections_total{type="Metrics listener",direction="received",state="rejected",family="ipv6"} 0
tor_relay_connections_total{type="Metrics",direction="initiated",state="created",family="ipv4"} 0
tor_relay_connections_total{type="Metrics",direction="initiated",state="created",family="ipv6"} 0
tor_relay_connections_total{type="Metrics",direction="received",state="created",family="ipv4"} 0
tor_relay_connections_total{type="Metrics",direction="received",state="created",family="ipv6"} 0
tor_relay_connections_total{type="Metrics",direction="received",state="rejected",family="ipv4"} 0
tor_relay_connections_total{type="Metrics",direction="received",state="rejected",family="ipv6"} 0
# HELP tor_relay_flag Relay flags from consensus
# TYPE tor_relay_flag gauge
tor_relay_flag{type="Fast"} 0
tor_relay_flag{type="Exit"} 0
tor_relay_flag{type="Authority"} 0
tor_relay_flag{type="Stable"} 0
tor_relay_flag{type="HSDir"} 0
tor_relay_flag{type="Running"} 0
tor_relay_flag{type="V2Dir"} 0
tor_relay_flag{type="Sybil"} 0
tor_relay_flag{type="Guard"} 0
# HELP tor_relay_circuits_total Total number of circuits
# TYPE tor_relay_circuits_total gauge
tor_relay_circuits_total{state="opened"} 0
# HELP tor_relay_streams_total Total number of streams
# TYPE tor_relay_streams_total counter
tor_relay_streams_total{type="BEGIN"} 0
tor_relay_streams_total{type="BEGIN_DIR"} 0
tor_relay_streams_total{type="RESOLVE"} 0
# HELP tor_relay_traffic_bytes Traffic related counters
# TYPE tor_relay_traffic_bytes counter
tor_relay_traffic_bytes{direction="read"} 0
tor_relay_traffic_bytes{direction="written"} 0
# HELP tor_relay_dos_total Denial of Service defenses related counters
# TYPE tor_relay_dos_total counter
tor_relay_dos_total{type="circuit_rejected"} 0
tor_relay_dos_total{type="circuit_killed_max_cell"} 0
tor_relay_dos_total{type="circuit_killed_max_cell_outq"} 0
tor_relay_dos_total{type="marked_address"} 0
tor_relay_dos_total{type="marked_address_maxq"} 0
tor_relay_dos_total{type="conn_rejected"} 0
tor_relay_dos_total{type="concurrent_conn_rejected"} 0
tor_relay_dos_total{type="single_hop_refused"} 0
tor_relay_dos_total{type="introduce2_rejected"} 0
# HELP tor_relay_load_onionskins_total Total number of onionskins handled
# TYPE tor_relay_load_onionskins_total counter
tor_relay_load_onionskins_total{type="tap",action="processed"} 0
tor_relay_load_onionskins_total{type="tap",action="dropped"} 0
tor_relay_load_onionskins_total{type="fast",action="processed"} 0
tor_relay_load_onionskins_total{type="fast",action="dropped"} 0
tor_relay_load_onionskins_total{type="ntor",action="processed"} 0
tor_relay_load_onionskins_total{type="ntor",action="dropped"} 0
tor_relay_load_onionskins_total{type="ntor_v3",action="processed"} 0
tor_relay_load_onionskins_total{type="ntor_v3",action="dropped"} 0
# HELP tor_relay_exit_dns_query_total Total number of DNS queries done by this relay
# TYPE tor_relay_exit_dns_query_total counter
tor_relay_exit_dns_query_total 0
# HELP tor_relay_exit_dns_error_total Total number of DNS errors encountered by this relay
# TYPE tor_relay_exit_dns_error_total counter
tor_relay_exit_dns_error_total{reason="success"} 0
tor_relay_exit_dns_error_total{reason="format"} 0
tor_relay_exit_dns_error_total{reason="serverfailed"} 0
tor_relay_exit_dns_error_total{reason="notexist"} 0
tor_relay_exit_dns_error_total{reason="notimpl"} 0
tor_relay_exit_dns_error_total{reason="refused"} 0
tor_relay_exit_dns_error_total{reason="truncated"} 0
tor_relay_exit_dns_error_total{reason="unknown"} 0
tor_relay_exit_dns_error_total{reason="tor_timeout"} 0
tor_relay_exit_dns_error_total{reason="shutdown"} 0
tor_relay_exit_dns_error_total{reason="cancel"} 0
tor_relay_exit_dns_error_total{reason="nodata"} 0
# HELP tor_relay_load_oom_bytes_total Total number of bytes the OOM has freed by subsystem
# TYPE tor_relay_load_oom_bytes_total counter
tor_relay_load_oom_bytes_total{subsys="cell"} 0
tor_relay_load_oom_bytes_total{subsys="dns"} 0
tor_relay_load_oom_bytes_total{subsys="geoip"} 0
tor_relay_load_oom_bytes_total{subsys="hsdir"} 0
# HELP tor_relay_load_socket_total Total number of sockets
# TYPE tor_relay_load_socket_total gauge
tor_relay_load_socket_total{state="opened"} 0
tor_relay_load_socket_total 0
# HELP tor_relay_load_tcp_exhaustion_total Total number of times we ran out of TCP ports
# TYPE tor_relay_load_tcp_exhaustion_total counter
tor_relay_load_tcp_exhaustion_total 0
# HELP tor_relay_load_global_rate_limit_reached_total Total number of global connection bucket limit reached
# TYPE tor_relay_load_global_rate_limit_reached_total counter
tor_relay_load_global_rate_limit_reached_total{side="read"} 0
tor_relay_load_global_rate_limit_reached_total{side="write"} 0

위 행이 실제로 뜻하는 바를 살펴보겠어요:

tor_relay_load_onionskins_total{type="ntor",action="dropped"} 0

중계기에 'dropped'(중단됨)이라는 글귀를 발견하셨다면, CPU나 RAM 쪽 문제인 경우가 일반적입빈다.

Tor is sadly single threaded except for when the "onion skins" are processed. 'onion skin'은 암호화기법이 적용된 작업으로, 잘 알려진 'onion 계층'을 대상으로 매 회로마다 적용돼야 작동해요.

Tor는 계층을 처리할 때 '스레드 풀'을 사용해요. 그리고 처리한 결과물을 스레드 풀에 위탁해요. 해당 스레드 풀에서 메모리나 CPU에서의 압박(pressure)으로 인해 작업이 중단될 수 있어요. 그럴 경우 과부하 상태가 작동(trigger)돼요.

서버의 모든 자원이 가동 중일 경우(at capacity), 과부하 상태가 작동될 가능성이 큽니다.

tor_relay_exit_dns_error_total{...}

Any counter in the "*_dns_error_total" realm (apart from the one for successful queries) indicates a potential DNS related problem. However, we realized during the 0.4.7 release cycle that DNS errors are way too noisy and contain too many false positives to be useful for overload reporting purposes. We therefore don't use them anymore for that purpose starting with 0.4.6.9 and 0.4.7.4-alpha. However, we still keep DNS metrics around to give the relay operator insight into what is going on with their relay.

DNS timeout issues and errors only apply to Exit nodes.

tor_relay_load_oom_bytes_total{...}

메모리 부족 발동(Out Of Memory invocation, OOM invocation)은 Ram 문제를 가리킵니다. 중계기의 Ram 용량 증설이 필요한 경우거나, 메모리 누수 문제일 수 있어요. tor 프로세스에서 메모리 누수를 발견하셨다면, 해당 문제를 Tor gitLab로 제보해주시거나, Tor 중계기 메일링 리스트에 기재된 주소로 이메일을 보내주세요.

Tor엔 자체적인 OOM 핸들러가 있어요. Tor 추정 상의 가용 메모리 중 75%가 점유되는 순간 핸들러가 발동돼요. Thus, let's say tor thinks it can use 2GB in total then at 1.5GB of memory usage, it will start freeing memory. 이러한 상태를 과부하 상태로 간주해요.

To estimate the amount of memory it has available, when tor starts, it will use MaxMemInQueues or, if not set, will look at the total RAM available on the system and apply this algorithm:

    if RAM >= 8GB {
      memory = RAM * 40%
    } else {
      memory = RAM * 75%
    }
    /* Capped. */
    memory = min(memory, 8GB) -> [8GB on 64bit and 2GB on 32bit)
    /* Minimum value. */
    memory = max(250MB, memory)

과부하 상태를 방지하려면, 2GB 이상의 램이 장착된 64비트 시스템에서 중계기를 운영하는 걸 권장해요. 4GB의 램 용량이 바람직해요. 물론 더 증설한다고 시스템적으로 해가 되는 건 결코 아니에요만. Note: If you are running a powerful server with lots of RAM then you might end up in an overloaded state due to the default queue size limit of 8GB even though you still have plenty of RAM unused. Add an appropriate MaxMemInQueues entry to your torrc configuration in that case.

Tor가 OS OOM 핸들러 자체에 의해 호출될 수도 있음을 신경쓰시는 분들도 계실 수 있어요. 이는 tor가 실행될 때 시스템의 총 메모리 용량을 가져오기 때문이에요. 시스템 전반에서 많은 애플리케이션이 램을 사용하면서 실행 중이라면, 종국에는 너무 많은 메모리가 점유되게 돼요. 이런 경우 OS는 OOM 트리거를 tor에 발동할 수 있어요. 이때 tor는 메모리 프레셔(memory pressure)를 인식하지 못한 상황이에요.

tor_relay_load_socket_total

If the number of opened sockets is close to or the same as total sockets available then this indicates the relay is running out of sockets. tor 프로세스를 대상으로 ulimit -n 값을 늘리면 해결돼요.

tor_relay_load_tcp_exhaustion_total

다음 행은 중계기가 TCP 포트에서 실행 중임을 나타냅니다.

sysctl상기된 바와 같이 조정(tune)해 보세요.

tor_relay_load_global_rate_limit_reached_total

해당 카운터가 짧은 시간 동안 상당한 수치량으로 증가한다면, 중계기가 혼잡한 겁니다. 큰 어니언 서비스 또는 네트워크에서의 DDoS에 의해 지킴이로 사용되고 있는 것 같아요.

중계기가 여전히 과부하 상태이고 원인 규명이 안 됐다면 network-report@torproject.org에 메일을 보내주세요. network-report OpenPGP key을 통해 메일을 암호화해 보낼 수 있어요.

When upgrading your Tor relay, or moving it to a different computer, be sure to keep the same identity keys (stored in keys/ed25519_master_id_secret_key and keys/secret_id_key in your DataDirectory).

If you are a bridge operator, also make sure to keep pt_state/. It contains data required for your bridge to keep working with the same bridge line.

For simplicity, just copying over the entire DataDirectory should work too.

You may wish to keep backups of these identity keys, plus pt_state for a bridge, so you can restore the relay if something goes wrong.

기본 공개 포트 목록이 하단에 있으면, 중계기 운영자가 torrc 구성이나 소스 코드 수정을 통해 모든 포트를 열어볼 수 있음을 명심하세요. 기본 출구 포트 목록을 소스 코드 릴리스 release-0.4.6의 src/or/policies.c (line 85line 1901)에서 확인 가능해요.

reject 0.0.0.0/8
reject 169.254.0.0/16
reject 127.0.0.0/8
reject 192.168.0.0/16
reject 10.0.0.0/8
reject 172.16.0.0/12

reject *:25
reject *:119
reject *:135-139
reject *:445
reject *:563
reject *:1214
reject *:4661-4666
reject *:6346-6429
reject *:6699
reject *:6881-6999
accept *:*

BridgeDB implements six mechanisms to distribute bridges: HTTPS, Moat, Email, Telegram, Settings and Reserved. 브리지 운영자는 중계기 검색에서 현재 배포 방식(mechanism)을 확인할 수 있어요. 주어진 빈칸 폼에 브리지의 <hashed fingerprint="핑거프린트"> 를 입력하고, "검색"을 클릭하세요.

브리지 운영자는 또한 사용할 배포 방식(distribution method)을 직접 선택할 수 있어요. To change the method, modify the BridgeDistribution setting in the torrc file to one of these: https, moat, email, telegram, settings, lox, none, any. You can find a description of each distributor in the rdsys distributors documentation.

브리지 설치 후 진행 가이드에서 더 알아보세요.

  • 중계기 종류 중 가장 필요한 건 출구 중게서버이에요. 하지만 해당 서버는 가장 큰 법적 노출과 위험을 안고 있기도 해요. (따라서 절대 집에서 출구 중계기를 돌리면 안 돼요)
  • 최소한의 노력으로 중계기를 운영할 방법을 찾고 계시다면, '빠른 지킴이 중계기' 또한 유용해요.
  • 브리지 다음으로

Tor 프로젝트는 Tor 중계기의 쉽고 간편한 설정에 주안점을 두고 개발하고 있어요:

  • 중계기가 종종 오프라인 상태로 들어가더라도 괜찮아요. 저장소에서 이를 빨리 감지해 해당 중계기로 다른 사용자를 전송하는 걸 중단할 겁니다. 너무 자주 오프라인 상태에 들어가지만 않게 관리해 주세요. 해당 중계기를 사용한 접속이 꺠질 수 있기 때문이에요.
  • 각 Tor 중계기엔 '출구 정책'이 있어, 어떤 종류의 아웃바운드 트래픽(outbound connections)을 허용하고 거부할지 규정하니다. 아무나 중계기를 거쳐가는 게 부담스러우시다면, 다른 Tor 중계기에서 온 접속만 허용하도록 설정할 수 있어요.
  • 중계기가 가진 대역폭 가용량은 tor에서 보수적으로 집계된 후 다른 네트워크에 공시돼요. 따라서 대역폭이 낮은 중계기 대비 대역폭이 큰 중계기에 더 많은 사용자가 유입돼요. 대역폭이 낮은 서버 역시 부차적으로 사용자가 할당되므로 유용한 건 마찬가지이에요.

중계기마다 부하에 차이가 있는 이유

Tor는 네트워크 전반의 대역폭을 관리해요. 대다수 중계기가 적절히 운영되도록 조처해요. Tor의 목표는 BitTorrent와 같은 프로토콜과 차이가 있어요. 저지연 웹페이지 환경은 Tor의 희망사항이에요. 그러려면 빠른 접속을 여유있게 제공하는 환경이 요구돼요. BitTorrent는 대량 다운로드를 희망하는 사용자들이 많이 이용하므로, 대역폭 전체 사용이 요구돼요.

현재 Tor 프로젝트에선 신규 대역폭 스캐너을 한창 개발하고 있어요. 기존대비 훨씬 쓰기 쉽고 유지보수하기도 쉽어요. 새로운 대역폭 스캐너로 측정되지 못했거나, 낮은 측정치를 보인 중계기에 대해 진단(diagnostics)할 겁니다.

Tor에 대역폭 스캐너가 필요한 이유가 있나요?

대다수 제공자에서 로컬 네트워크의 최대 속도를 안내하고 있어요. 하지만, Tor를 사용하는 사용자는 전 세계에 두루 있고, 이들은 한 개 혹은 두 개의 중계기에 임의로 배정돼 접속돼요. 따라서 Tor는 해당 중계기가 전 세계의 네트워크에 잘 접속할 수 있는지 확인해야만 해요

So even if all relay operators set their advertised bandwidth to their local connection speed, we would still need bandwidth authorities to balance the load between different parts of the Internet.

'표준 중계기 부하량'은 무엇인가요?

대부분의 중계기에선 실제 처리량 대비 30%~80%의 부하 수준(loaded)을 보이는 게 일반적이에요. 클라이언트 입장에선 위와 같이 설정돼있는 게 낫어요. 과도하게 부하가 걸린 증계서버에의 지연시간(latency)가 길어질 수 있기 때문이에요. (Tor는 각 중계기의 부하가 10% 수준에 머물 수 있도록, 많은 중계기가 있었으면 해요. 부하량이 그 수준에 이르면 일반적인 인터넷 만큼 Tor의 속도가 빨라질 거에요.)

중계기가 느린 원인으로 종종 프로세서가 느려진 점, 접속이 제한량이 이른 점이 꼽히기도 해요. 그 외엔 보통 네트워크가 느린 게 중계기가 느린 원인이에요: 다른 Tor 중계기와의 접속이 불량이거나, 두 접속 사이의 거리가 멀기 때문에 느려지는 거예요.

중계기를 제한하는 요소를 알아내는 방법

중계기를 느리게 하는 요소는 다양해요. 해당 요소를 찾아내는 방법을 지금부터 알아보겠어요.

시스템 제한

  • RAM, CPU, 중계기의 소켓/파일 기술자(socket/file descriptor) 사용량을 살펴보세요.

Tor는 시작 시 이러한 요소를 로그로 기록해둡니다. 다른 요소를 'top'과 같은 도구(tool)로 조회할 수 있어요.

서비스 제공자(provider)에 의한 대역폭 제한

  • 중계기 제공자와 다른 중계기간 인터넷 대등접속(대역폭, 지연 속도)를 확인하세요. 미국의 인터넷 서비스 제공자인 Comcast를 통해 전송되는 중계기는 속도가 종종 느립니다. 북미와 서유럽 이외 지역에서의 중계기도 일반적으로 해당 지역대비 느립니다.

Tor Network 제한

중계기 대역폭이 중계기 자체 측정치로 제한되거나, 디렉터리 기관에서의 측정치로 제한될 수 있어요. 어떤 기준으로 중계기의 대역폭이 제한되고 있는지 다음 문답을 통해 알아낼 수 있어요:

  • 중계기에 제시된 각 투표를 합의 건전성(큰 페이지)에서 확인하세요. 그리고 중앙값도 확인하세요. 귀하의 중계기에 '디렉터리 기관에서 운영 중(Running by some directory authorities)'이라 표시돼있지 않다면:
    • 잘못된 IPv4 주소나 IPv6 주소로 설정돼있지 않던가요?
    • 다른 네트워크에서 중계기의 IPv4나 IPv6 주소에 접근할 수 있던가요?
    • 운영하는 중계기의 IPv4 주소에 여러 중계기가 있진 않던가요?

위 문답에 모두 해당하지 않는다면, 운영하는 중계기의 자체 대역폭 측정치(observed bandwidth)와 자체 대역폭 제한 측정치(bandwidth rate 혹은 limit)를 확인해보세요. Look up your relay on Metrics. '대역폭' 항목에 마우스를 갖다 대면, '관측된 대역폭'과 '중계기의 대역폭 비율'이 표시돼요.

좀 더 구체적인 예시를 확인하세요: 합의의 가중치 하락 and 출구 중계기의 속도 향상.

해결 방법

두 수치 중 가장 작은 게 중계기에 할당된 대역폭 제한량이에요.

  • 두 수치 중 작은 게 '대역폭 비율(bandwidth rate)'이라면, torrc에 있는 옵션인 BandwidthRate/Burst나 RelayBandwidthRate/Burst를 높게 조정하세요.
  • 두 수치 중 작은 게 '관측된 대역폭(observed bandwidth)'이라면, 자체 측정값이 늘어나지 않는 한, 현재 대역폭에서 더 증가하지 않아요. 중계기가 느린 원인을 찾아내야 해요.
  • 대역폭 측정치의 중앙값(median)에 해당할 경우, 중계기를 대다수 대역폭 기관에서 느리다고 간주한 거예요. 이 경우엔 왜 대역폭 기관에서 중계기를 느리다고 봤는지 알아봐야 해요

중계기 측정을 직접 해보기

귀하의 중계기가 자체적으로 느리다고 진단한 경우거나 대역폭 기관에서 느리다고 본 경우라면, 직접 대역폭을 테스트해볼 수 있어요:

  • Run a test using tor to see how fast tor can get on your network

    For this, you need to configure a tor client to use use your relay as entry. If your relay has only Guard flag, set EntryNodes with your relay fingerprint in torrc. If your relay doesn't have Guard flag or it has Guard and Exit flags, you can't set your relay as an entry node (see https://gitlab.torproject.org/tpo/core/tor/-/issues/22204), but you can set it as your bridge, even if it is not a bridge. To set your relay as a bridge, add to your torrc:

    Bridge <ip>:<port>
    UseBridge 1
    

    Then download a large file using your SocksPort as a socks proxy. For this, you can use curl, eg:

    curl https://target/path --proxy socks5h://<user>:<password>@127.0.0.1:<socks-port>
    

    Using different user/password guarantees different circuits. You can use $RANDOM.

    That will give you some idea of how much traffic your relay can sustain.

    Alternatively, you can run relay_bw to test your relay using 2 hops circuits, in a similar way as sbws does.

  • Run a test using tor and chutney to find out how fast tor can get on your CPU. Keep increasing the data volume until the bandwidth stops increasing.

네, 그렇어요. 몇몇 공격을 대상으로 익명성을 기존보다 더 확고히 할 수 있게 돼요.

가장 간단한 예시로 일부 Tor 중계기를 점거한 공격자를 들어보겠어요. 공격자는 Tor 중계기를 점거했으므로, 보낸 접속을 보게 될 겁니다. 하지만 해당 접속이 컴퓨터에서 처음 보낸 것인지, 아니면 타인의 중계기를 거쳐 온 것인지 알 길이 없어요.

중계기의 양이 항상 익명성 증진에 도움이 되는 것은 아님을 보여주는 사례도 있어요: 공격자가 수발신 트래픽을 모두 볼 수 있다면, 어떤 게 중계기에서 온 트래픽이고, 어떤 트래픽이 컴퓨터에서 처음 발신됐는지 파악하는 건 공격자에게 쉬운 일이 돼요. (해당 사례에서 그들은 목적지까지의 트래픽을 볼 수 있는 게 아닌 이상, 여전히 목적지를 알지 못해요. 단지 평범한 클라이언트와 하등 다를 게 없다는 것만 파악할 뿐이에요.)

Tor 중계기를 운영할 때의 한계가 이것 외에도 몇 개 더 있어요. 첫째, Tor 프로젝트에서 보유한 중계기가 수백개에 불과하지만, 그 중 하나를 운영한다는 사실 자체가 공격자로 하여금 익명성에 높은 가치를 두는 인물임을 파악할 수 있는 기제로 작용해요. 두 번째, 중계기를 운영할때의 지식을 활용한 난해한 공격 방식도 종종 확인돼요. 예를 들어, 설사 공격자가 네트워크를 보지 않는다 하더라도, 그들이 트래픽을 전송하는지 여부를 '관측(observe)'할 수 있어요. 이는 Tor 중계기에 트래픽을 중계하는 과정에서 트래픽 타이밍의 변화를 파악함으로써 가능해요.

리스크를 감당할만큼 이점이 클지는 연구를 좀 더 해와야 결론을 내릴 수 있을 거 같어요. 가장 걱정하시는 공격에 많은 영향을 받아요. 대다수 사용자에게 있어, 이러한 조치는 훌륭하다고 봅니다.

NAT/라우터 기기에서 포트 포워딩을 하는 절차를 portforward.com에서 알아보세요.

중계기가 내부망에서 실행 중이라면, 포트 포워딩 설정이 필요해요. TCP 접속 포워딩은 시스템에 따라 다릅니다. 하지만 방화벽에 관련 자주 묻는 질문 항목에 기재된 예해가 유효할 수 있으니 확인해보세요.

또한 GNU/Linux에서 iptables를 사용한 방법을 예시로 보여드리면 다음과 같어요:

/sbin/iptables -A INPUT -i eth0 -p tcp --destination-port 9001 -j ACCEPT

외부 인터페이스(인터넷에 접속된 부분)가 다르다면 "eth0"를 변경해야 할 수 있어요. 인터페이스가 하나만 있을 가능성이 있어요(루프백 인터페이스 제외). 따라서 찾는 거 자체는 그렇게 어렵지 않을 겁니다.

torrc 파일 내에 있는 '계정 옵션'을 통해 주어진 시간동안 중계기에서 사용하는 최대 바이트 수를 설정할 수 있어요.

    AccountingStart day week month [day] HH:MM

위 옵션으로 계정을 언제 초기화할지 지정할 수 잇어요. 예를 들어 주당 제공되는 총 바이트 수를 설정하려면(매주 수요일 오전 10:00에 초기화 돼요), 다음과 같이 설정하세요:

    AccountingStart week 3 10:00
    AccountingMax 500 GBytes

This specifies the maximum amount of data your relay will send during an accounting period, and the maximum amount of data your relay will receive during an accounting period. (AccountingStart에서 설정한) 집계 기간이 초기화되면, AccountingMax 계수기가 0으로 초기화돼요.

된예시: 하루에 오고가는 트래픽 양을 50 GB로 설정하고, 집계가 매일 정오에 초기화되는 상황을 가정해봅시다.

    AccountingStart day 12:00
    AccountingMax 50 GBytes

집계 기간이 초기화된 직후에 중계기가 바로 깨지는 않을 수 있음을 유의하세요. 중계기에서 지난 집계기간이 초기화되고 새로운 집계기간 설정 후 깨어나는 사이에 지난 기간동안 얼마나 빠르게 할당량이 빠져나갔는지를 추적하고, 임의 지점을 선택해야 하기 때문이에요. Tor는 이 방식으로 수백 개의 중계기가 월초에 한꺼번에 재시작하지 않도록 할뿐 아니라, 깨지 않는 문제도 방지하고 있어요.

접속 속도 대비 후원할만한 대역폭 양이 적으시다면, 일일 집계 설정을 사용하시는 걸 추천해요. 일일 집계 설정 시 1일차에 월 할당량을 다 쓰는 일을 미연에 방지할 수 있어요. 간단하게 월별 제공량을 30으로 나눠보세요. 한편 개인적으로 평소보다 대역폭을 많이 쓰는 날도 있을 수 있으므로, 이를 고려해 rate의 설정치를 보수적으로 잡을 필요가 있어요: XGB를 각 방향에 저공하고자 한다면, RelayBandwidthRate 값을 20*X KBytes로 설정하면 돼요. 예를 들어, 50GB를 각 경로에 제공하고자 한다면, RelayBandwidthRate 를 1000 KBytes로 설정하면 되겠죠: 중계기는 이런 식으로도 적어도 반나절은 Tor 네트워크에 기여할 수 있어요.

    AccountingStart day 0:00
    AccountingMax 50 GBytes
    RelayBandwidthRate 1000 KBytes
    RelayBandwidthBurst 5000 KBytes # 로 평균 수준을 유지하면서도 버스트 값을 높게 잡을 수 있어요

제대로 보신 게 맞어요. 대개 Tor 중계기에 투입되는 바이트는 나가는 양과 들어가는 양이 같어요. 그러나 예외가 있어요:

DirPort를 열었다면, Tor 클라이언트는 디렉터리의 복사본을 요청해요. Tor 클라이언트의 요청(HTTP GET)에 쓰이는 정보량은 꽤 적어요. 그러나 응답에 쓰이는 정보량은 꽤 많아요. 쓰기 'byte 바이트 수와' '읽기' 바이트 수가 차이 나는 원인 대부분은 이러한 현상에서 기인해요.

중계기가 출구 노드로 작동될 때도 예외에 해당해요. 나가는 접속(exit connection)에서 정보를 읽고(예시: 인스턴트 메시지나 ssh 접속), 이를 Tor 네트워크로 보내기 위해 전체 512 바이트로 압축하기 때문이에요.

AccountingMaxBandwidthRate에 할당된 매개변수는 클라이언트와 Tor 프로세스의 중계기 기능 둘 다 적용돼요. 따라서 Tor가 하이버네이션 상태일 때는 브라우징이 불가능하다고 뜨게 돼요. Tor 로그에 이러한 항목이 있으면 Tor가 절전 상태이에요:

Bandwidth soft limit reached; commencing hibernation.
No new connections will be accepted

이 상태를 해결하려면 두 개의 Tor 프로세스를 실행하면 돼요. 중계기와 클라이언트를 각각 하나씩을, 서로 다르게 설정해서 실행하세요. 위와 같이 실행하려면 (작동중인 중계기 설정에서 시작할 경우) 다음 절차를 따르세요:

  • Tor 중계기의 torrc 파일에서 SocksPort를 0으로 설정하세요.
  • torrc.sample로 새 클라이언트 torrc 파일을 생성하세요. 그 후 주어진 중계기에서 서로 다른 로그 파일을 생성하는지 확인하세요. 새로 만든 torrc 파일명을 torrc.client와 torrc.relay로 설정하는 게 그동안의 관례이에요.
  • Tor 클라이언트와 Tor 중계기의 스크립트에 -f /path/to/correct/torrc 를 추가해 수정하세요.
  • Linux/BSD/macOS의 경우, 시작 스크립트를 Tor.client and Tor.relay 로 바꾸는 게 설정을 분리하는 데 있어 더 쉬울 수 있어요.

간결히 표현하자면, 다음과 같이 작동돼요:

  • "ed25519_master_id_secret_key"로 명명된 ed25519 주 신원 비밀 키(primary ed25519 identity secret key) 파일이 있어요. 해당 키는 가장 중요한 키이에요. 따라서 보안이 철저한 위치에 백업해 보관하셔야 해요. 파일에 그만큼 민감한 정보가 많기에 잘 보호해야 해요. 해당 키를 따로 생성한 후 비밀번호 입력 창이 떴을 때 비밀번호를 입력하면 Tor가 자체적으로 이를 암호화할 수 있어요.
  • 'ed25519_signing_secret_key'라 명명된 중단기 서명키(medium term signing key)는 Tor에서 사용되는 목적으로 생성돼요. 또한 'ed25519_signing_cert'로 명명된 인증서(certificate)도 생성돼요. '주 신원 비밀키'(primary identity secret key)로 서명돼있고, '중단기 서명키'가 주어진 시기 동안 유효하다는 것이 주 신원 비밀키에 의해 확인돼있어요. 중단기 서명키의 기본 유효기간(validity)은 30일이에요. 다만 이는 torrc 내 "SigningKeyLifetime N days|weeks|months" 옵션을 조정해 변경할 수 있어요.
  • "ed25519_master_id_public_key"로 명명된 '주 공개 키'(primary public key)도 있어요. 네트워크에 공시된 중계기의 실제 신원에 해당해요. "ed5519_master_id_secret_key"은 강제로 풀기도 어렵고, 그렇다고 그 안에 민감한 정보가 많은 것도 아니에요.

Tor는 중단기 서명 키와 인증서에 유효성 여부 정보만 확인하기 위해 접근해요. 따라서 '주 신원 비밀 키'를 DataDirectory/keys에서 꺼내 외부 저장소나 다른 컴퓨터에 보관해도 돼요. 이를 외부에 옮긴다면, 중단기 서명 키와 인증서를 만료 전에 수동으로 갱신해야 해요. 그러지 않으면 중계 서버에서 작동 중인 Tor 프로세스가 만료로 인해 중단돼요.

해당 기능은 선택 사항이에요. 원하지 않으면 사용할 필요가 없어요. 주기적으로 중단기 서명키를 수동으로 재갱신하지 않은 채 별도의 조작 없이(unattended) 중개 서버가 장기적으로 운영되기를 원한다면, '주 신원 비밀키'를 원 위치인 DataDirectory/keys에 두세요. Tor 재설치를 대비한 백업 정도만 따로 해두세요. 이 기능을 사용하려면, 해당 주제를 자세하게 다룬 가이드를 참고하세요.

이제 지킴이가 되었기 때문에, 클라이언트가 다른 포지션에서는 덜 사용하고 있지만, 아직 지킴이로 사용하기 위해 기존 지킴이를 교체한 경우는 많지 않아요. 이 블로그 포스트Changing of the Guards: A Framework for Understanding and Improving Entry Guard Selection in Tor을 읽어보세요

출구가 구성되지 않았거나 악의적일 경우, BadExit 플래그가 부여돼요. BadExit 플래그를 Tor가 확인함으로써 해당 중게서버를 통해 나가는 걸 피할 수 있어요. 그 결과 BadExit 플래그가 붙은 해당 중계기가 출구로서 기능을 못 하게 되는거죠. 만일 중계기에 이 플래그가 붙었다면, 이는 Tor가 트래픽 경로를 정하는 과정에서 출구로 설정한 중계기에서 문제를 발견했거나, 의심스러운 활동을 탐지했는데 귀하와의 연락이 되지 않았기 때문이에요. 불량 중계기 팀에 연락하시면 Tor 프로젝트에서 문제를 해결할 수 있어요.

반드시 모든 발신 접속을 허용하도록 설정해야 해요. 그래야 각 중계회선이 다른 중계회선과 통신할 수 있어요.

Tor 중계기 운영자는 공통 통신 규약에 의해 적법하게 보호받어요. 즉 ISP의 네트워크를 거쳐간 제3자 컨텐츠에 대한 책임을 현지 ISP에서 부담하지 않는 게 공통 통신 규약에 규정돼있는데, 이것이 Tor 중계기 운영자에게도 적용되는 거예요.. 트래픽을 필터링하는 출구 중계기에는 위와 같은 규약에 의한 보호가 박탈돼요,

Tor는 간섭 및 개입이 없는 자유로운 네트워크 접속을 장려해요. 출구 중계기를 거쳐 인터넷에 접속하려는 트래픽을 필터링하지 말아야 해요.. 트래픽을 필터링하는 걸로 밝혀진 출구 중계기엔 BadExit 플래그가 부여돼요.

아주 좋아요. 여러 개의 중계기를 운영해 Tor 네트워크에 기여하고자 하신다면, 저희 입장에선 아주 감사하죠. 하지만 수십개의 중계기를 동일한 네트워크 상에서 운영하진 마세요. Tor 네트워크의 목표는 분산과 확산에 있어요.

여러 개의 중계기를 운영하고자 하신다면, torrc에 있는 'MyFamily' 구성 옵션을 각 중계기마다 설정해주세요. 통제 가능한 모든 중계기 리스트(CSV, 각 항목을 콤마로 구분해 기재됐어요)는 다음과 같어요:

MyFamily $fingerprint1,$fingerprint2,$fingerprint3

각 지문는 (띄어쓰기 없는) 40글자의 신원 지문(identity fingerprint)이에요.

이런 방식으로, Tor 클라이언트는 단일 회로 상에서 여러 개의 중계기를 사용하면 안 됨을 경험적으로 알게 돼요. 컴퓨터나 네트워크 상에서 관리자 권한을 갖고 있다면, 설사 지리적 위지가 동일하지 않다 하더라도 MyFamily를 설정해야 해요.

torrc 파일에 추가할 수 있는 옵션으로 두 개가 있어요:

BandwidthRate 로 장기 대역폭 최대 허용치(bytes per second)를 설정할 수 있어요. 가령 "BandwidthRate 10 MBytes"를 10 megabytes per second (a fast connection)로 조정하거나 "BandwidthRate 500 KBytes"를 500 kilobytes per second (a decent cable connection)로 조정할 수 있어요. BandwidthRate 최소치는 75 kilobytes per second 이에요.

BandwidthBurst 짧은 시간 동안 BandwidthRate 보다 많은 트래픽이 요청된 경우 이를 충당하기 위해 사전에 모아둔 바이트 비축분을 말해요. 그러면서도 장기적으로 볼 때 설정된 BandwidthRate의 평균치를 충족할 수 있도록 관리돼요. 즉 Rate를 낮게 설정하고 Burst를 높게 설정한 정책을 적용할 경우, 피크 시간대에 더 많은 트래픽을 받아들일 수 있으면서도 장기적으로는 평균치를 유지할 수 있는 거예요. 예를 들어 "BandwidthBurst 500 KBytes" 로 설정하고, 동일 수치를 BandwidthRate에도 적용할 경우, 500 kilobytes per second 을 초과하지 상황이 절대 발생하지 않아요; 하지만 BandwidthBurst 를 (5 MBytes 와 같이) BandwidthRate보다 높은 값으로 설정할 경우, 비축분이 동날 때까지 더 많은 데이터가 사용될 수 있어요.

귀하가 케이블 모뎀과 같이 (업로드가 다운로드보다 낮은) 비대칭 접속 환경 인 경우, 상대적으로 대역폭이 작어요. 따라서 반드시 BandwidthRate를 대역폭(일반적으론 업로드 대역폭이에요) 대비 낮게 설정해야 해요. 그렇게 설정하지 않을 경우, 최대 대역폭 사용량에 도달한 기간 동안 많은 패킷 손실이 발생하게 돼요. 따라서 어떤 값으로 설정했을 때 접속이 가장 쾌적하게 이루어지는지 여러 값을 집어넣어서 찾아보세요. 그런 후 BandwidthBurst와 BandwidthRate 값을 동일하게 설정하세요.

Linux 기반 Tor 노드는 별개의 독자적인 옵션이 존재해요: 해당 노드는 주어진 기기에서 Tor 트래픽의 우선순위를 다른 트래픽보다 우선시할 수 있어요. 이를 통해 해당 노드 사용자의 트래픽은 Tor 부하에 영향을 받지 않게 되는 거죠. 위와 같이 하는 방법을 설명한 문서를 Tor의 source distribution내 contrib 디렉터리에서 살펴볼 수 있어요.

Additionally, there are hibernation options where you can tell Tor to only serve a certain amount of bandwidth per time period (such as 100 GB per month). These are covered in the hibernation entry.

BandwidthRate와 BandwidthBurst의 설정 단위는 Bytes지, Bits가 아님에 유의하세요.