Skip to content
KitploitKITPLOIT
도구블로그
제출
도구블로그
제출

해킹, 침투 테스트 및 사이버 보안 도구를 당신의 보안 무기고에!

Kitploit은 해킹, 사이버 보안 및 침투 테스트 도구 디렉토리입니다. 최신 프로젝트 업데이트를 발견하여 취약점을 찾고, 시스템을 분석하고, 테스트를 자동화하고, 보안을 강화하세요.

··피드·문의·개인정보·© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
toxiproxy — ⏰ 🔥 카오스 및 복원력 테스트를 위해 네트워크 및 시스템 상태를 시뮬레이션하는 TCP 프록시 | Kitploit
도구/GitHubGitHub/shopify/toxiproxy
General Purpose UtilitiesWeb Proxies & InterceptionChaos Engineering
GitHubshopify/toxiproxy

toxiproxy

⏰ 🔥 카오스 및 복원력 테스트를 위해 네트워크 및 시스템 상태를 시뮬레이션하는 TCP 프록시

저장소 보기
12.3k50819일 전Kitploit 검토 완료

인기

모두 보기 →

커뮤니티에서 가장 많이 사용되는 도구를 찾아보세요.

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

Toxiproxy

GitHub release Build Status

Toxiproxy는 네트워크 상태를 시뮬레이션하기 위한 프레임워크입니다. 테스트, CI 및 개발 환경에서 작동하도록 특별히 만들어졌으며, 연결에 대한 결정적 변조를 지원하면서도 무작위 혼란과 사용자 지정도 지원합니다. Toxiproxy는 테스트를 통해 애플리케이션에 단일 실패 지점이 없음을 입증하는 데 필요한 도구입니다. 우리는 2014년 10월부터 Shopify의 모든 개발 및 테스트 환경에서 이를 성공적으로 사용해 왔습니다. 복원력에 대한 자세한 내용은 [블로그 게시물][blog]을 참조하세요.

Toxiproxy 사용은 두 부분으로 구성됩니다. Go로 작성된 TCP 프록시(이 저장소에 포함된 것)와 HTTP를 통해 프록시와 통신하는 클라이언트입니다. 애플리케이션이 모든 테스트 연결이 Toxiproxy를 통과하도록 구성한 다음 HTTP를 통해 연결 상태를 조작할 수 있습니다. 프로젝트를 설정하는 방법은 아래 사용법을 참조하세요.

예를 들어, Ruby 클라이언트에서 MySQL의 응답에 1000ms의 지연을 추가하려면:```ruby Toxiproxy[:mysql_master].downstream(:latency, latency: 1000).apply do Shop.first # this takes at least 1s end

root@kitploit:~
모든 Redis 인스턴스를 종료하려면:```ruby
Toxiproxy[/redis/].down do
  Shop.first # this will throw an exception
end

이 README의 예제는 현재 Ruby로 작성되어 있지만, 다른 언어로 클라이언트를 만드는 것을 막는 것은 없습니다 (Clients 참조).

Table of Contents

  • Toxiproxy
    • Table of Contents
    • Why yet another chaotic TCP proxy?
    • Clients
    • Example
    • Usage
      • 1. Installing Toxiproxy
        • Upgrading from Toxiproxy 1.x
      • 2. Populating Toxiproxy
      • 3. Using Toxiproxy
      • 4. Logging
      • Toxics
        • latency
        • down
        • bandwidth
        • slow_close
        • timeout
        • reset_peer
        • slicer
        • limit_data
        • packet_loss
      • HTTP API
        • Proxy fields:
        • Toxic fields:
        • Endpoints
        • Populating Proxies
      • CLI Example
      • Metrics
      • Frequently Asked Questions
      • Development
      • Release

왜 또 다른 혼돈(chaotic) TCP 프록시인가?

우리가 찾은 기존 도구들은 통합 테스트와 단위 테스트에 필요한 동적 API를 제공하지 못했습니다. Linux 도구인 nc 등은 크로스 플랫폼을 지원하지 않고 root 권한이 필요하여 테스트, 개발, CI 환경에서 문제가 됩니다.

Clients

  • toxiproxy-ruby
  • toxiproxy-go
  • toxiproxy-python
  • toxiproxy.net
  • toxiproxy-php-client
  • toxiproxy-node-client
  • toxiproxy-java
  • toxiproxy-haskell
  • toxiproxy-rust
  • toxiproxy-elixir

Example

Rails 애플리케이션을 사용한 예제를 살펴보겠습니다. Toxiproxy는 결코 Ruby에 묶여 있지 않으며, 단지 우리의 첫 번째 사용 사례였을 뿐입니다. 전체 예제는 sirupsen/toxiproxy-rails-example에서 볼 수 있습니다. 바로 시작하려면 Usage로 내려가세요.

인기 있는 블로그에서 어떤 이유로 게시물의 태그를 Redis에 저장하고 게시물 자체는 MySQL에 저장한다고 가정해 봅시다. Redis set에서 태그를 조작하는 몇 가지 메서드를 포함하는 Post 클래스가 있을 수 있습니다.```ruby class Post < ActiveRecord::Base

Return an Array of all the tags.

def tags TagRedis.smembers(tag_key) end

Add a tag to the post.

def add_tag(tag) TagRedis.sadd(tag_key, tag) end

Remove a tag from the post.

def remove_tag(tag) TagRedis.srem(tag_key, tag) end

Return the key in Redis for the set of tags for the post.

def tag_key "post:tags:#{self.id}" end end

root@kitploit:~
태그 데이터 저장소에 쓰는 동안(추가/제거) 오류가 발생하는 것은 괜찮다고 결정했습니다.
그러나 태그 데이터 저장소가 다운된 경우에는
태그 없이 게시물을 볼 수 있어야 합니다. 간단히
`Redis::CannotConnectError`를 `tags` 메서드의 `SMEMBERS` Redis 호출 주변에서
rescue하면 됩니다. 이를 테스트하기 위해 Toxiproxy를 사용합시다.

이미 Toxiproxy를 설치했고 컴퓨터에서 실행 중이므로
2단계로 건너뛸 수 있습니다. 여기에서 Toxiproxy가 Redis 태그에 대한 매핑을
가지고 있는지 확인해야 합니다. `config/boot.rb`(연결이 이루어지기 전)에 다음을 추가합니다:```ruby
require 'toxiproxy'

Toxiproxy.populate([
  {
    name: "toxiproxy_test_redis_tags",
    listen: "127.0.0.1:22222",
    upstream: "127.0.0.1:6379"
  }
])

그런 다음 config/environments/test.rb에서 TagRedis를 Toxiproxy를 통해 Redis에 연결하는 Redis 클라이언트로 설정하기 위해 다음 줄을 추가합니다:```ruby TagRedis = Redis.new(port: 22222)

root@kitploit:~
테스트 환경의 모든 호출은 이제 Toxiproxy를 거칩니다. 즉, 실패를 시뮬레이션하는 단위 테스트를 추가할 수 있습니다:```ruby
test "should return empty array when tag redis is down when listing tags" do
  @post.add_tag "mammals"

  # Take down all Redises in Toxiproxy
  Toxiproxy[/redis/].down do
    assert_equal [], @post.tags
  end
end

The test fails with Redis::CannotConnectError. Perfect! Toxiproxy took down the Redis successfully for the duration of the closure. Let's fix the tags method to be resilient:```ruby def tags TagRedis.smembers(tag_key) rescue Redis::CannotConnectError [] end

root@kitploit:~
테스트가 통과합니다! 이제 Redis가 다운되었을 때 태그를 가져오면 예외를 던지는 대신 빈 배열을 반환한다는 것을 증명하는 단위 테스트가 생겼습니다. 전체 커버리지를 위해서는 Redis가 다운되었을 때 블로그 포스트 페이지 전체를 가져오는 것을 포함하는 통합 테스트도 작성해야 합니다.

전체 예제 애플리케이션은
[sirupsen/toxiproxy-rails-example](https://github.com/sirupsen/toxiproxy-rails-example)에 있습니다.

## 사용법

Toxiproxy를 사용하도록 프로젝트를 구성하는 것은 세 단계로 이루어집니다:

1. Toxiproxy 설치
2. Toxiproxy 채우기
3. Toxiproxy 사용

### 1. Toxiproxy 설치

**Linux**

최신 바이너리와 시스템 패키지는 [`Releases`](https://github.com/Shopify/toxiproxy/releases)를 참조하세요.

**Ubuntu**```bash
$ wget -O toxiproxy-2.1.4.deb https://github.com/Shopify/toxiproxy/releases/download/v2.1.4/toxiproxy_2.1.4_amd64.deb
$ sudo dpkg -i toxiproxy-2.1.4.deb
$ sudo service toxiproxy start

OS X

Homebrew로:```bash $ brew tap shopify/shopify $ brew install toxiproxy

root@kitploit:~
또는 [MacPorts](https://www.macports.org/):```bash
$ port install toxiproxy

Windows

Toxiproxy for Windows는 https://github.com/Shopify/toxiproxy/releases/download/v2.1.4/toxiproxy-server-windows-amd64.exe 에서 다운로드할 수 있습니다.

Docker

Toxiproxy는 Github 컨테이너 레지스트리에서 사용할 수 있습니다. 이전 버전 <= 2.1.4는 Docker Hub에서 사용할 수 있습니다.```bash $ docker pull ghcr.io/shopify/toxiproxy $ docker run --rm -it ghcr.io/shopify/toxiproxy

root@kitploit:~
다른 컨테이너가 아닌 호스트에서 Toxiproxy를 사용하는 경우, `--net=host`로 호스트 네트워킹을 활성화하십시오.```shell
$ docker run --rm --entrypoint="/toxiproxy-cli" -it ghcr.io/shopify/toxiproxy list

Go가 설치되어 있다면, make 파일을 사용하여 Toxiproxy를 소스에서 빌드할 수 있습니다:```bash $ make build $ ./toxiproxy-server

root@kitploit:~
#### Toxiproxy 1.x에서 업그레이드

Toxiproxy 2.0에서는 API에 여러 변경 사항이 적용되어 1.x 버전과 호환되지 않습니다.
Toxiproxy 서버 2.x 버전을 사용하려면 클라이언트 라이브러리가 동일한 버전을 지원하는지
확인해야 합니다. `/version` 엔드포인트를 확인하면 실행 중인 Toxiproxy 버전을
알 수 있습니다.

특정 라이브러리 변경 사항은 해당 클라이언트 라이브러리 문서를 참조하세요. Toxiproxy 서버의 자세한
변경 사항은 [CHANGELOG.md](https://github.com/shopify/toxiproxy/blob/HEAD/CHANGELOG.md)에서 확인할 수 있습니다.

### 2. Toxiproxy 채우기

애플리케이션이 부팅될 때 Toxiproxy가 어떤 엔드포인트를 어디로 프록시할지 알 수 있도록
해야 합니다. 주요 매개변수는 이름, Toxiproxy가 **수신(listen)**할 주소, 그리고
업스트림의 주소입니다.

일부 클라이언트 라이브러리에는 이 작업을 위한 헬퍼가 있으며, 이는 기본적으로 목록의 각
프록시가 생성되도록 하는 것입니다. Ruby 클라이언트의 예시:```ruby
# Make sure `shopify_test_redis_master` and `shopify_test_mysql_master` are
# present in Toxiproxy
Toxiproxy.populate([
  {
    name: "shopify_test_redis_master",
    listen: "127.0.0.1:22220",
    upstream: "127.0.0.1:6379"
  },
  {
    name: "shopify_test_mysql_master",
    listen: "127.0.0.1:24220",
    upstream: "127.0.0.1:3306"
  }
])

이 코드는 부팅 시 가능한 한 빨리, 어떤 코드가 Toxiproxy를 통한 연결을 설정하기 전에 실행되어야 합니다. population 헬퍼에 대한 문서는 클라이언트 라이브러리에서 확인하시기 바랍니다.

또는 CLI를 사용하여 프록시를 생성할 수도 있습니다. 예:```bash toxiproxy-cli create -l localhost:26379 -u localhost:6379 shopify_test_redis_master

root@kitploit:~
다음과 같은 명명 규칙을 권장합니다: `<app>_<env>_<data store>_<shard>`.
이렇게 하면 동일한 Toxiproxy를 사용하는 애플리케이션 간에 충돌이 발생하지 않습니다.

대규모 애플리케이션의 경우 Toxiproxy 구성을 별도의 구성 파일에 저장하는 것이 좋습니다. `config/toxiproxy.json`을 사용합니다. 이 파일은 `-config` 옵션으로 서버에 전달하거나, 애플리케이션에서 로드하여 `populate` 함수와 함께 사용할 수 있습니다.

`config/toxiproxy.json` 예시:```json
[
  {
    "name": "web_dev_frontend_1",
    "listen": "[::]:https://raw.githubusercontent.com/shopify/toxiproxy/HEAD/18080%22,
    "upstream": "webapp.domain:8080",
    "enabled": true
  },
  {
    "name": "web_dev_mysql_1",
    "listen": "[::]:13306",
    "upstream": "database.domain:3306",
    "enabled": true
  }
]

임의의 포트 충돌을 피하려면 임시 포트 범위 밖의 포트를 사용하세요. Linux에서는 기본적으로 32,768~61,000이며, 다음을 참조하세요. /proc/sys/net/ipv4/ip_local_port_range.

3. Toxiproxy 사용하기

Toxiproxy를 사용하려면 이제 애플리케이션이 Toxiproxy를 통해 연결하도록 구성해야 합니다. 2단계의 예시를 이어서, Redis 클라이언트가 Toxiproxy를 통해 연결되도록 구성할 수 있습니다:```ruby

old straight to redis

redis = Redis.new(port: 6380)

new through toxiproxy

redis = Redis.new(port: 22220)

root@kitploit:~
이제 Toxiproxy API를 통해 이를 변조할 수 있습니다. Ruby에서:```ruby
redis = Redis.new(port: 22220)

Toxiproxy[:shopify_test_redis_master].downstream(:latency, latency: 1000).apply do
  redis.get("test") # will take 1s
end

또는 CLI를 통해:```bash toxiproxy-cli toxic add -t latency -a latency=1000 shopify_test_redis_master

root@kitploit:~
Please consult your respective client library on usage.

### 4. Logging

There are the following log levels: panic, fatal, error, warn or warning, info, debug and trace.
The level could be updated via environment variable `LOG_LEVEL`.

### Toxics

Toxics manipulate the pipe between the client and upstream. They can be added
and removed from proxies using the [HTTP api](#http-api). Each toxic has its own parameters
to change how it affects the proxy links.

For documentation on implementing custom toxics, see [CREATING_TOXICS.md](https://github.com/shopify/toxiproxy/blob/HEAD/CREATING_TOXICS.md)

#### latency

Add a delay to all data going through the proxy. The delay is equal to `latency` +/- `jitter`.

Attributes:

 - `latency`: time in milliseconds
 - `jitter`: time in milliseconds

#### down

Bringing a service down is not technically a toxic in the implementation of
Toxiproxy. This is done by `POST`ing to `/proxies/{proxy}` and setting the
`enabled` field to `false`.

#### bandwidth

Limit a connection to a maximum number of kilobytes per second.

Attributes:

 - `rate`: rate in KB/s

#### slow_close

Delay the TCP socket from closing until `delay` has elapsed.

Attributes:

 - `delay`: time in milliseconds

#### timeout

Stops all data from getting through, and closes the connection after `timeout`. If
`timeout` is 0, the connection won't close, and data will be dropped until the
toxic is removed.

Attributes:

 - `timeout`: time in milliseconds

#### reset_peer

Simulate TCP RESET (Connection reset by peer) on the connections by closing the stub Input
immediately or after a `timeout`.

Attributes:

 - `timeout`: time in milliseconds

#### slicer

Slices TCP data up into small bits, optionally adding a delay between each
sliced "packet".

Attributes:

 - `average_size`: size in bytes of an average packet
 - `size_variation`: variation in bytes of an average packet (should be smaller than average_size)
 - `delay`: time in microseconds to delay each packet by

#### limit_data

Closes connection when transmitted data exceeded limit.

 - `bytes`: number of bytes it should transmit before connection is closed

#### packet_loss

Randomly drops chunks flowing through the proxy simulating
flaky Wi-Fi, mobile, or satellite network conditions.

Attributes:
 - `loss_rate`: probability [0.0-1.0] that a chunk is dropped (default 0.0)
 - `correlation`: extra drop probability when the previous chunk was dropped, modeling burst loss (default 0.0)

### HTTP API

All communication with the Toxiproxy daemon from the client happens through the
HTTP interface, which is described here.

Toxiproxy listens for HTTP on port **8474**.

#### Proxy fields:

 - `name`: proxy name (string)
 - `listen`: listen address (string)
 - `upstream`: proxy upstream address (string)
 - `enabled`: true/false (defaults to true on creation)

To change a proxy's name, it must be deleted and recreated.

Changing the `listen` or `upstream` fields will restart the proxy and drop any active connections.

If `listen` is specified with a port of 0, toxiproxy will pick an ephemeral port. The `listen` field
in the response will be updated with the actual port.

If you change `enabled` to `false`, it will take down the proxy. You can switch it
back to `true` to reenable it.

#### Toxic fields:

 - `name`: toxic name (string, defaults to `<type>_<stream>`)
 - `type`: toxic type (string)
 - `stream`: link direction to affect (defaults to `downstream`)
 - `toxicity`: probability of the toxic being applied to a link (defaults to 1.0, 100%)
 - `attributes`: a map of toxic-specific attributes

See [Toxics](#toxics) for toxic-specific attributes.

The `stream` direction must be either `upstream` or `downstream`. `upstream` applies
the toxic on the `client -> server` connection, while `downstream` applies the toxic
on the `server -> client` connection. This can be used to modify requests and responses
separately.

#### Endpoints

All endpoints are JSON.

 - **GET /proxies** - List existing proxies and their toxics
 - **POST /proxies** - Create a new proxy
 - **POST /populate** - Create or replace a list of proxies
 - **GET /proxies/{proxy}** - Show the proxy with all its active toxics
 - **POST /proxies/{proxy}** - Update a proxy's fields
 - **DELETE /proxies/{proxy}** - Delete an existing proxy
 - **GET /proxies/{proxy}/toxics** - List active toxics
 - **POST /proxies/{proxy}/toxics** - Create a new toxic
 - **GET /proxies/{proxy}/toxics/{toxic}** - Get an active toxic's fields
 - **POST /proxies/{proxy}/toxics/{toxic}** - Update an active toxic
 - **DELETE /proxies/{proxy}/toxics/{toxic}** - Remove an active toxic
 - **POST /reset** - Enable all proxies and remove all active toxics
 - **GET /version** - Returns the server version number
 - **GET /metrics** - Returns Prometheus-compatible metrics

#### Populating Proxies

Proxies can be added and configured in bulk using the `/populate` endpoint. This is done by
passing a json array of proxies to toxiproxy. If a proxy with the same name already exists,
it will be compared to the new proxy and replaced if the `upstream` and `listen` address don't match.

A `/populate` call can be included for example at application start to ensure all required proxies
exist. It is safe to make this call several times, since proxies will be untouched as long as their
fields are consistent with the new data.

### CLI Example```bash
$ toxiproxy-cli create -l localhost:26379 -u localhost:6379 redis
Created new proxy redis
$ toxiproxy-cli list
Listen          Upstream        Name  Enabled Toxics
======================================================================
127.0.0.1:26379 localhost:6379  redis true    None

Hint: inspect toxics with `toxiproxy-client inspect <proxyName>`

입력된 번역할 내용(chunk 41)이 비어 있습니다. 번역할 텍스트가 제공되지 않아 번역을 진행할 수 없습니다. 원문 내용을 다시 제공해 주시면 번역해 드리겠습니다.```bash $ redis-cli -p 26379 127.0.0.1:26379> SET omg pandas OK 127.0.0.1:26379> GET omg "pandas"

root@kitploit:~
입력 텍스트가 제공되지 않아 번역할 내용이 없습니다.```bash
$ toxiproxy-cli toxic add -t latency -a latency=1000 redis
Added downstream latency toxic 'latency_downstream' on proxy 'redis'

I received no input content to translate. Please provide the chunk text.```bash $ redis-cli -p 26379 127.0.0.1:26379> GET omg "pandas" (1.00s) 127.0.0.1:26379> DEL omg (integer) 1 (1.00s)

root@kitploit:~
번역할 마크다운 원문을 제공해 주세요.```bash
$ toxiproxy-cli toxic remove -n latency_downstream redis
Removed toxic 'latency_downstream' on proxy 'redis'

The input chunk appears to be empty — no source text was provided for chunk 49 of 55. Please supply the Markdown content to translate.```bash $ redis-cli -p 26379 127.0.0.1:26379> GET omg (nil)

root@kitploit:~
The input content for chunk 51 is missing — the message ends with "INPUT:" but no text follows. Please resend the chunk content and I'll translate it into Korean.```bash
$ toxiproxy-cli delete redis
Deleted proxy redis

(no content provided)```bash $ redis-cli -p 26379 Could not connect to Redis at 127.0.0.1:26379: Connection refused

root@kitploit:~
### 메트릭

Toxiproxy는 HTTP API의 /metrics에서 Prometheus 호환 메트릭을 노출합니다.
전체 설명은 [METRICS.md](https://github.com/shopify/toxiproxy/blob/HEAD/METRICS.md)를 참조하세요.

### 자주 묻는 질문

**Toxiproxy는 얼마나 빠른가요?** Toxiproxy의 속도는 주로 하드웨어에 따라 달라지지만, 활성화된 toxic이 없을 때 *< 100µs*의 지연 시간을 기대할 수 있습니다. Macbook Pro에서 `GOMAXPROCS=4`로 실행했을 때 *~1000MB/s* 처리량을 달성했으며, 고급 데스크톱에서는 *2400MB/s*까지 달성했습니다. 기본적으로 Toxiproxy는 테스트 중인 앱만큼은 빠르게 데이터를 이동할 수 있습니다.

**Toxiproxy는 무작위 테스트를 할 수 있나요?** 사용 가능한 많은 toxic은 무작위성을 갖도록 구성할 수 있습니다. 예를 들어 `latency` toxic의 `jitter` 같은 것입니다. 또한 toxic이 영향을 미칠 연결 비율을 지정하는 전역 `toxicity` 매개변수가 있습니다. 이것은 연결의 X%가 타임아웃되도록 허용하는 `timeout` toxic과 같은 경우에 가장 유용합니다.

**MySQL에서 Toxiproxy 작업이 반영되지 않습니다**. 일부 클라이언트의 경우 호스트가 `localhost`로 설정되어 있으면 포트를 무엇으로 전달하든 MySQL은 로컬 Unix 도메인 소켓을 선호합니다. MySQL 서버가 소켓을 생성하지 않도록 구성하고 호스트로 `127.0.0.1`을 사용하세요. 서버를 재시작한 후에는 이전 소켓을 제거하는 것을 잊지 마세요.

**Toxiproxy가 간헐적인 연결 실패를 일으킵니다**. 무작위 포트 충돌을 피하려면 임시(ephemeral) 포트 범위 밖의 포트를 사용하세요. Linux에서 기본적으로 `32,768`에서 `61,000`까지이며, `/proc/sys/net/ipv4/ip_local_port_range`를 참조하세요.

**애플리케이션마다 Toxiproxy를 실행해야 하나요?** 아니요, 모든 애플리케이션에 동일한 Toxiproxy를 사용하는 것을 권장합니다. 서비스를 구분하기 위해 프록시 이름을 `<app>_<env>_<data store>_<shard>` 패턴으로 지정하는 것을 권장합니다. 예: `shopify_test_redis_master` 또는 `shopify_development_mysql_1`.

### 개발

* `make`. 현재 플랫폼용 toxiproxy 개발 바이너리를 빌드합니다.
* `make all`. 모든 플랫폼용 Toxiproxy 바이너리와 패키지를 빌드합니다. Linux 및 Darwin(amd64)에서 크로스 컴파일이 활성화된 Go와, Linux 패키지 바이너리를 빌드하기 위해 `$PATH`에 [`goreleaser`](https://goreleaser.com/)가 필요합니다.
* `make test`. Toxiproxy 테스트를 실행합니다.

### 릴리스

[RELEASE.md](https://github.com/shopify/toxiproxy/blob/HEAD/RELEASE.md)를 참조하세요.

[blog]: https://shopify.engineering/building-and-testing-resilient-ruby-on-rails-applications
도구 다운로드