중계서버 운영자

Tor 프로젝트는 Tor 중계서버의 쉽고 간편한 설정에 주안점을 두고 개발하고 있습니다:

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

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

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

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

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

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

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

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

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)에 해당할 경우, 귀하의 중계서버를 대다수 대역폭 기관에서 느리다고 간주한 것입니다. 이 경우엔 왜 대역폭 기관에서 귀하의 중계서버를 느리다고 봤는지 알아봐야 합니다

중계서버 측정을 직접 해보기

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

  • 현재 네트워크 및 CPU 환경에서 Tor가 낼 수 있는 속도를 Tor에서 테스트를 돌려 알아보세요.
  • 현재 CPU 환경에서 tor가 얼마나 빨리 작동되는지 tor와 chutney로 테스트를 돌려보세요. 대역폭 증가 추세가 멈출 때까지 데이터 양을 계속 늘려보세요.

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가 아님에 유의하세요.

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

  • "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 재설치를 대비한 백업 정도만 따로 해두세요. 이 기능을 사용하려면, 해당 주제를 자세하게 다룬 가이드를 참고하세요.

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

  • 우분투 저장소의 패키지를 사용하지 마세요. 패키지로는 안정적인 업데이트가 불가능합니다. 즉 우분투 저장소를 사용하면 중요한 안정성과 보안 패치를 놓칠 수 있다는 것입니다.
  • 다음 명령을 실행하여 우분투 버전을 확인하십시오:
     ‪$ 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
    

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), 과부하 상태가 작동될 가능성이 큽니다.

The ntor and ntor_v3 values will be the same at the moment which is a bug we need to fix.

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%가 점유되는 순간 핸들러가 발동됩니다. 그러므로, tor 추산한 총 가용 메모리인 2GB 중에서1.5기가의 메모리가 사용됐다고 할 때, OOM 핸들러로 메모리를 비우기 시작할 겁니다. 이러한 상태를 과부하 상태로 간주합니다.

가용 메모리 용량을 추산하기 위해, tor가 실행할 때 MaxMemInQueues 명령도 같이 실행됩니다. 해당 명령이 설정되지 않았을 경우, 시스템에서 가용 램 용량을 확인한 후 다음의 알고리즘을 적용합니다:

    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의 램 용량이 바람직합니다. 물론 더 증설한다고 시스템적으로 해가 되는 건 결코 아닙니다만.

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

해당 카운터가 짧은 시간 동안 상당한 수치량으로 증가한다면, 중계서버가 혼잡한 겁니다. 해당 중계서버가 대형 onion 서비스에서 '가드' 노드로 사용되고 있을 가능성이 큽니다. 혹은 DDoS 공격이 해당 네트워크에서 진행 중일 가능성도 있습니다.

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

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

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

MyFamily $fingerprint1,$fingerprint2,$fingerprint3

각 지문는 (띄어쓰기 없는) 40글자의 신원 지문(identity fingerprint)입니다.

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

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

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

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

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

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

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

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

따라서 입력된 옛 IP 주소가 수정되지 않는다면, '주소' 구성 옵션을 통해 원하는 IP를 특정할 수 없는 것입니다. 컴퓨터에 NAT가 적용돼있고 내부 IP 주소밖에 없다면, 동적 IP 주소에 대한 다음의 지원 항목을 참고하세요.

한편 IP 주소가 많을 경우, 'OutboundBindAddress'을 설정해 외부에 표시하고자 하는 IP 주소로 외부 연결을 받고자 할 수 있습니다.

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 account 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 중계서버 운영자는 공통 통신 규약에 의해 적법하게 보호받습니다. 즉 ISP의 네트워크를 거쳐간 제3자 컨텐츠에 대한 책임을 현지 ISP에서 부담하지 않는 게 공통 통신 규약에 규정돼있는데, 이것이 Tor 중계서버 운영자에게도 적용되는 것입니다.. 트래픽을 필터링하는 출구 중계서버에는 위와 같은 규약에 의한 보호가 박탈됩니다,

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

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

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

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

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

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

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

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

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

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

Tor 중계서버를 업그레이드 하거나 다른 컴퓨터로 옮길 때, ( "keys/ed25519_master_id_secret_key" 에 저장돼있고, DataDirectory 내 "keys/secret_id_key" 에 저장된) 신원 키를 동일하게 유지해야 하는 것이 중요합니다. 향후 중계서버를 복구할 수 있도록 신원 키를 계속 백업해두는 걸 추천합니다. 이래야 중계서버의 평판이 훼손되는 일을 미연에 방지할 수 있습니다.

즉 Tor 중계서버를 업그레이드 하면서 동일한 torrc 및 DataDirectory를 유지해야 업그레이드가 제대로 진행되며, 중계서버에서 동일한 키를 계속 사용할 수 있습니다. DataDirectory를 새로 선정하는 경우, 기존의 keys/ed25519_master_id_secret_key 와 keys/secret_id_key 를 복사해뒀는지 사전에 꼭 확인하세요.

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

참고: Tor 0.2.7의 경우, 중계서버에 ed25519 타원 곡선 암호화 기법을 기반으로 한 새로운 차세대 식별 방식을 사용하고 있습니다. 따라서 기존 RSA 식별 방식 키가 새로운 방식으로 대체됩니다. 하지만 구버전과의 호환성을 보장하는 차원에서 지금 당장 적용되진 않습니다. 그 때까지, 각 중계서버는 모두 ed25519 신원 (신원 키 파일: keys/ed25519_master_id_secret_key) 와 RSA 신원(신원 키 파일: keys/secret_id_key)을 보유하게 됩니다. 중계서버를 복원하는 경우, DataDirectory를 변경하는 경우, 중계서버를 새로운 컴퓨터로 옮기는 경우를 모두 대비해, 둘 다 복사해서 백업해두세요.

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

집에서 돌리는 대신에, Tor에 호의적인 상업 시설에서 출구 중계서버를 돌리는 걸 고려해 보세요. 귀하의 출구 중계서버 IP 주소가 가정의 IP 주소와 다르도록 관리하고, 귀하의 트래픽이 거길 거치지 않도록 하세요. 출구 중계서버로 호스팅 중인 컴퓨터에 민감한 개인 정보를 저장해두는 것도 당연히 피하셔야 합니다.

Debian, 혹은 특히 Ubuntu를 사용하시는 경우, Tor 프로젝트 저장소에서 Tor를 설치하는 게 훨씬 좋습니다.

  • ulimit -n 수치는 32768 정도가 필요한 모든 연결을 개방한 상태로 유지할만큼 충분히 높습니다.
  • Tor에만 사용할 용도로 생성한 사용자 프로필이므로, Tor를 실행할 때 루트 권한을 부여하지 않아도 됩니다.
  • init 스크립트가 포함돼있으므로, Tor가 시작 프로그램으로서 부팅 시 실행됩니다.
  • Tor 구성 파일(config file)에 문제가 없는지 파악하기 위해, --verify-config가 Tor와 같이 실행됩니다.
  • Tor를 저수준 포트(low-level port)에 바인딩한 후, 권한을 없앨 수 있습니다.

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

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

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

기본 공개 포트 목록이 하단에 있습니다만, 중계서버 운영자가 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, none, any.

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

Tor는 동적 IP 주소로 중계서버를 무난하게 다룰 수 있습니다. 귀하의 torrc 주소 행을 공란으로 두세요. 그러면 Tor가 알아맞힐 겁니다.

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 로 바꾸는 게 설정을 분리하는 데 있어 더 쉬울 수 있습니다.

귀하의 중계서버가 가드 노드로 설정됐습니다. 따라서 클라이언트가 다른 위치에 있을 때보다 적게 쓰는 것입니다. 그러나 기존 가드 노드 기능으로 중계서버가 재배치(rotate)되는 경우는 그리 많지 않습니다. 이 블로그 포스트Changing of the Guards: A Framework for Understanding and Improving Entry Guard Selection in Tor을 읽어보세요

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

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

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인 것은 흔하지 않습니다.