Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions nat.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,15 @@ def transform(packet)
return unless entry

entry.packets_sent += 1
entry.bytes_sent += packet.bytes.length
entry.bytes_sent += packet.bytes.size
packet.src_addr = @global_addr
packet.l4.src_port = entry.global_port
else
entry = table.lookup_ingress(packet)
return unless entry

entry.packets_received += 1
entry.bytes_received += packet.bytes.length
entry.bytes_received += packet.bytes.size
packet.dest_addr = entry.local_addr
packet.l4.dest_port = entry.local_port
end
Expand All @@ -59,7 +59,7 @@ def handle_icmp_error(packet)
return if entry.nil?

entry.packets_received += 1
entry.bytes_received += packet.bytes.length
entry.bytes_received += packet.bytes.size
packet.l4.original.src_addr = entry.local_addr
packet.l4.original.l4.src_port = entry.local_port
packet.dest_addr = entry.local_addr
Expand Down
47 changes: 39 additions & 8 deletions nattable.rb
Original file line number Diff line number Diff line change
Expand Up @@ -121,10 +121,10 @@ def _gc_entry(entry)

def _insert(local_addr, local_port, global_port, remote_addr, remote_port)
entry = Entry.new
entry.local_addr = local_addr
entry.local_addr = local_addr.dup
entry.local_port = local_port
entry.global_port = global_port
entry.remote_addr = remote_addr
entry.remote_addr = remote_addr.dup
entry.remote_port = remote_port

entry.link(@anchor)
Expand Down Expand Up @@ -154,6 +154,8 @@ def log(event, local_addr, local_port, global_port, remote_addr, remote_port, ot
end

class SymmetricNATTable < NATTable
ZERO_STR = "\0".b * (16 + 2) * 2

def empty_port(remote_addr, remote_port)
gc
20.times do
Expand All @@ -164,23 +166,43 @@ def empty_port(remote_addr, remote_port)
end

def local_key_from_packet(packet)
packet.tuple + packet.l4.tuple
l3_tuple = packet.tuple
l3_tuple_size = l3_tuple.size

key = ZERO_STR.byteslice(0, l3_tuple_size + 4)
IO::Buffer.for(key) do |b|
b.copy(l3_tuple)
b.copy(packet.l4.tuple, l3_tuple_size)
end

key
end

def local_key_from_tuple(local_addr, local_port, remote_addr, remote_port)
local_addr + remote_addr + [local_port, remote_port].pack('n*')
local_addr.get_string + remote_addr.get_string + [local_port, remote_port].pack('n*')
end

def remote_key_from_packet(packet)
packet.src_addr + packet.l4.tuple
src_addr = packet.src_addr
addr_size = src_addr.size

key = ZERO_STR.byteslice(0, addr_size + 4)
IO::Buffer.for(key) do |b|
Copy link

@ioquatix ioquatix Jan 9, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's neat idea, I didn't think about it. Maybe we can do the similar:

IO::Buffer.string(size) do |buffer|
  # ...
end # => string

At the end, the buffer would be transferred to string zero copy.

Copy link
Owner Author

@kazuho kazuho Jan 9, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That interface SGTM (though I wonder if there should be a static function as part of String that generates a fixed-length, zero-filled bytes). I'm all in to optimizations that reduce the conversion cost bet. the two types.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That seems a nice addition, and it's easy to support without extra copying on TruffleRuby, unlike the current usage here (would need one copy to go from Rope to byte[] internally).

b.copy(src_addr)
b.copy(packet.l4.tuple, addr_size)
end

key
end

def remote_key_from_tuple(global_port, remote_addr, remote_port)
remote_addr + [remote_port, global_port].pack('n*')
remote_addr.get_string + [remote_port, global_port].pack('n*')
end
end

class ConeNATTable < NATTable
ZERO_STR = "\0".b * (16 + 2)

def empty_port(_remote_addr, _remote_port)
gc
@empty_ports = global_ports.dup if @empty_ports.nil?
Expand All @@ -195,11 +217,20 @@ def _gc_entry(entry)
end

def local_key_from_packet(packet)
packet.src_addr + [packet.l4.src_port].pack('n')
src_addr = packet.src_addr
addr_size = src_addr.size

key = ZERO_STR.byteslice(0, addr_size + 2)
IO::Buffer.for(key) do |b|
b.copy(src_addr)
b.set_value(:U16, addr_size, packet.l4.src_port)
end

key
end

def local_key_from_tuple(local_addr, local_port, _remote_addr, _remote_port)
local_addr + [local_port].pack('n')
local_addr.get_string + [local_port].pack('n')
end

def remote_key_from_packet(packet)
Expand Down
2 changes: 1 addition & 1 deletion rat.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ def rack_handler
$nat = Nat.new

# global address is 192.168.0.139
$nat.global_addr = "\xc0\xa8\x0\x8b".b
$nat.global_addr = IO::Buffer.for("\xc0\xa8\x0\x8b".b)

# create TCP, UDP, ICMP Echo tables
$nat.tcp_table = SymmetricNATTable.new('tcp')
Expand Down
4 changes: 2 additions & 2 deletions reflector.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@

require './tun'

TRUE_ADDR = "\xa\1\2\xfe".b
FAKE_ADDR = "\xa\1\2\4".b
TRUE_ADDR = IO::Buffer.for("\xa\1\2\xfe".b)
FAKE_ADDR = IO::Buffer.for("\xa\1\2\4".b)

tun = Tun.new('rat')
loop do
Expand Down
Loading