Sploitus

Exploit for toxiproxy

kitploit ยท 2026-08-31

Exploit Code

MARKDOWN527 lines
## https://sploitus.com/exploit?id=KITPLOIT:TOOLS-GITHUB-SHOPIFY-TOXIPROXY
# Toxiproxy

![GitHub release](https://img.shields.io/github/release/Shopify/toxiproxy.svg) ![Build Status](https://github.com/Shopify/toxiproxy/actions/workflows/test.yml/badge.svg)

![](https://assets.kitploit.com/production/public/readmes/placeholders/f0fc86cfe65f76d40e15aaec61704ec8220a56dc89d4be03c46f67cb31b9fa8c.svg)

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