使用pfctl和dnctl在OSX 10.10上进行stream量整形

我正在尝试通过pfctldnctl在Mac OS X 10.10上进行stream量整形(节stream)。

我已经实现了一个简单的testing服务器和客户端netcat( nc )和一个合成的随机有效载荷文件,以validation我的dummynetpipe道节stream是否正常工作。 到目前为止,尝试使用Murus防火墙GUI应用程序来configurationdummynetpipe道似乎不能正确地阻止通信(64MB传输在〜200ms内完成)。

这是一个OSX bash shell脚本(需要brew install coreutils for gdate ),这是一个完整的例子。 如果你在一个terminal运行它:

 ./throttle-test.sh server 

另一个为

 ./throttle-test.sh client 

他们会尝试在您的en0接口上传输一个64MB的有效载荷(不使用lo0因为它的巨大MTU与WANstream量不相似)。

我也testing过将文件传输到远程Linux笔记本电脑,看是否源IP和目的IP都是本地IP绕过节stream,但即使是我的局域网/无线networking上的远程机器,速度比限制速度快得多。

我的问题是什么是一个正确的脚本来configurationpfctldnctl来限制这个文件传输到一个给定的带宽限制(比如说8mbps)。 限制的范围可以是特定的TCP端口。

注意OS X 10.10不再包含ipfw所以我正在寻找使用pfctldnctl东西。

这是我的throttle-test.sh文件:

 #!/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 "$@" 

更新

这是我迄今为止。 这似乎对下载方向正确工作,但在上传方向上完全不加油门。

 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 } 

这是我在El Capitan 10.11上使用的一个脚本,取得了一些成功:

 #!/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 

唯一相关的区别似乎是no dummynet quick on lo0 allno dummynet quick on lo0 all ,我不知道它是什么,在这里find: https : no dummynet quick on lo0 all