RubyでTAPを使ったトンネリングプログラムを実装してみる

こちらのサイトでシンプルなPythonの実装が配布されていたので、Rubyでも実装してみました。

require "socket"
TUNSETIFF = 0x400454ca
IFF_TAP = 0x0002
PEER = "192.168.0.100"
PORT = 9876
tap = open("/dev/net/tun", "r+")
tap.ioctl(TUNSETIFF, ["tap%d", IFF_TAP].pack("a16S"))
sock = UDPSocket.open
sock.bind("0.0.0.0", 9876)
peer = Socket.pack_sockaddr_in(PORT, PEER)
while true
    ret = IO::select([sock, tap])
    ret[0].each do |d|
        if d == tap
            sock.send(tap.read(1500), 0, peer)
        else
            tap.write(sock.recv(65535))
        end
    end
end

RubyでもTAPの読み書きが出来るしselectも使えるしioctlも発行できるよー、っと。