modelado de tráfico en OSX 10.10 con pfctl y dnctl

modelado de tráfico en OSX 10.10 con pfctl y dnctl

Estoy intentando configurar (regular) el tráfico en Mac OS X 10.10 a través de pfctly dnctl.

He implementado un servidor y un cliente de prueba simples con netcat ( nc) y un archivo de carga útil aleatorio sintético para verificar si la aceleración de mi tubería dummynet está funcionando correctamente. Hasta ahora, intentar configurar la tubería dummynet usando elAplicación GUI del cortafuegos murusno parece acelerar correctamente el tráfico (la transferencia de 64 MB se completa en ~200 ms).

Aquí hay un script de shell bash de OSX (requiere brew install coreutilsfor gdate) que es un ejemplo completo. Si lo ejecuta en una terminal como:

./throttle-test.sh server

y otro como

./throttle-test.sh client

Intentarán transferir una carga útil de 64 MB a través de su en0interfaz (no la usarán lo0porque su enorme MTU no es análoga al tráfico WAN).

También probé la transferencia del archivo a una computadora portátil Linux remota para ver si la IP de origen y de destino, ambas IP locales, pasaban por alto la limitación, pero incluso en una máquina remota en mi LAN/wifi la velocidad es mucho más rápida que el límite limitado.

Mi pregunta es cuál sería el script correcto para configurar pfctly dnctlacelerar la transferencia de este archivo a un límite de ancho de banda determinado (por ejemplo, 8 mbps). El alcance de la limitación puede ser un puerto TCP específico.

Tenga en cuenta que OS X 10.10 ya no lo incluye, ipfwasí que estoy buscando algo que use pfctly dnctl.

Aquí está mi throttle-test.sharchivo:

#!/bin/bash
set -o errexit    # always exit on error
set -o errtrace   # trap errors in functions as well
set -o pipefail   # don't ignore exit codes when piping output
set -o posix      # more strict failures in subshells
# set -x          # enable debugging

IFS="$(printf "\n\t")"

setup_payload() {
  local payload_path="$1"
  local size_kbytes="$2"
  mkdir -p $(basename "${payload_path}")

  if [[ -f "${payload_path}" ]]; then
    local on_disk=$(wc -c < "${payload_path}")
  fi
  if [[ ${on_disk} -ne $((${size_kbytes} * 1024)) ]]; then
    echo "creating payload file ${payload_path}"
    dd if=/dev/urandom of="${payload_path}" \
      bs=1024 count="${size_kbytes}" &> /dev/null
  fi
}

start_server() {
  local payload_path="$1"
  local ip="$2"
  local port="$3"
  while true; do
    echo "Starting netcat server for ${payload_path} on ${ip}:${port}"
    nc -l "${ip}" "${port}" < "${payload_path}"
    sleep 1
  done
}

hash() {
  shasum -a 256 "$1" | cut -d " " -f 1
}

verify_hashes() {
  # Sanity check no funny business
  from_hash=$(hash "$1")
  to_hash=$(hash "$2")
  if [[ "${from_hash}" != "${to_hash}" ]]; then
    echo "checksums did not match ${from_hash} ${to_hash}" 1>&2
    exit 10
  fi
}

client() {
  local payload_path="$1"
  local ip="$2"
  local port="$3"

  # time how long it takes to transfer the payload file
  start=$(gdate +%s%3N)
  nc -d "${ip}" "${port}" > "${payload_path}.client"
  stop=$(gdate +%s%3N)

  verify_hashes "${payload_path}" "${payload_path}.client"

  local duration=$((${stop} - ${start}))
  echo "${duration}"
}

main() {
  local size_kbytes=$((64 * 1024)) # 64 MB
  local payload_path="/tmp/throttle-test/data-${size_kbytes}.bin"
  local port="${PORT-9112}"
  # You may need to change this if you are on linux
  local interface="${INTERFACE-en0}"
  local ip=$(ipconfig getifaddr "${interface}")

  setup_payload "${payload_path}" "${size_kbytes}"
  case "$1" in
    server)
      start_server "${payload_path}" "${ip}" "${port}"
    ;;
    client)
      local duration=$(client "${payload_path}" "${ip}" "${port}")
      echo "Transfered ${size_kbytes} kbytes in ${duration} ms"
    ;;
    *)
      echo "Usage: $0 <server|client>"
    ;;
  esac
}

main "$@"

Actualizar

Esto es lo que tengo hasta ahora. Esto parece funcionar correctamente para la dirección de descarga, pero no acelera en absoluto en la dirección de carga.

throttle_start() {
  local down_mbps="$1"
  local up_mbps="$2"
  local delay=$(($3 / 2))
  sudo dnctl pipe 1 config bw "${down_mbps}Mbit/s" delay "${delay}"
  sudo dnctl pipe 2 config bw "${up_mbps}Mbit/s" delay "${delay}"
  (cat /etc/pf.conf && \
    echo 'dummynet-anchor "throttle"' && \
    echo 'anchor "throttle"') | sudo pfctl -f -
  cat << EOF | sudo pfctl -a throttle -f -
dummynet in quick proto tcp from any port = 9112 to any pipe 1
dummynet out quick proto tcp from any to any port = 9112 pipe 2
EOF
  sudo pfctl -q -e
}

Respuesta1

Este es un script que utilicé en El Capitan 10.11 con cierto éxito:

#!/bin/bash

# Reset dummynet to default config
dnctl -f flush

# Compose an addendum to the default config: creates a new anchor
(cat /etc/pf.conf &&
  echo 'dummynet-anchor "my_anchor"' &&
  echo 'anchor "my_anchor"') | pfctl -q -f -

# Configure the new anchor
cat <<EOF | pfctl -q -a my_anchor -f -
no dummynet quick on lo0 all
dummynet out proto tcp from any to any port 1:65535 pipe 1
EOF

# Create the dummynet queue
dnctl pipe 1 config bw 40000byte/s

# Activate PF
pfctl -E

# to check that dnctl is properly configured: sudo dnctl list

La única diferencia relevante parece ser el no dummynet quick on lo0 all, que realmente no sé qué hace, que se encuentra aquí:https://www.reddit.com/r/osx/comments/3g7dim/limiting_bandwidth_per_application/

información relacionada