em-udp-proxy 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ pkg/
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gem 'eventmachine'
data/README ADDED
@@ -0,0 +1,12 @@
1
+ EventMachine based UDP proxy.
2
+
3
+ Example usage:
4
+
5
+ > em-udp-proxy -a 127.0.0.1 -p 5001 -A 192.168.1.1 -P 5001
6
+
7
+ Starts the proxy binded to 127.0.0.1 with port 5001 and forwards traffic to/from 192.168.1.1 on port 5001.
8
+
9
+ TODO:
10
+ 1. More documentation :-)
11
+ 2. Remove Client objects for inactive clients (after certain threshold).
12
+ 3. Add some way to get stats from it.
@@ -0,0 +1,2 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
@@ -0,0 +1,23 @@
1
+ #!/usr/bin/env ruby
2
+ require 'rubygems'
3
+ require File.expand_path('../lib/udp_proxy.rb', File.dirname(__FILE__))
4
+ require 'optparse'
5
+
6
+ options = {}
7
+
8
+ OptionParser.new do |opts|
9
+ opts.banner = "Usage: em-udp-proxy [options]"
10
+
11
+ opts.on('-a', '--address ADDRESS', String, "Address to use") { |value| options[:address] = value }
12
+ opts.on('-p', '--port PORT', Numeric, "Listening port") { |value| options[:port] = value }
13
+ opts.on('-A','--remote-address ADDRESS', String, "Remote address to connect to") { |value| options[:remote_address] = value}
14
+ opts.on('-P','--remote-port PORT', Numeric, "Remote port to connect to") { |value| options[:remote_port] = value}
15
+
16
+ opts.on_tail("-h", "--help", "Show this message") do
17
+ puts opts
18
+ exit
19
+ end
20
+ end.parse!
21
+
22
+ Kernel.abort "Missing arguments, see --help for details." if options.length < 4
23
+ UDPProxy.start options[:address], options[:port], options[:remote_address], options[:remote_port]
@@ -0,0 +1,18 @@
1
+ $:.push File.expand_path("../lib", __FILE__)
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = "em-udp-proxy"
5
+ s.version = "0.1.0"
6
+ s.platform = Gem::Platform::RUBY
7
+ s.authors = ["Arik Fraimovich"]
8
+ s.email = ["arik@arikfr.com"]
9
+ s.homepage = "http://github.com/arikfr/em-udp-proxy"
10
+ s.summary = %q{EventMachine UDP Proxy}
11
+ s.description = s.summary
12
+
13
+ s.add_dependency "eventmachine"
14
+
15
+ s.files = `git ls-files`.split("\n")
16
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
17
+ s.require_paths = ["lib"]
18
+ end
@@ -0,0 +1,30 @@
1
+ require 'eventmachine'
2
+ require 'syslog'
3
+ require 'socket'
4
+ require File.expand_path('./udp_proxy/server.rb', File.dirname(__FILE__))
5
+ require File.expand_path('./udp_proxy/client.rb', File.dirname(__FILE__))
6
+
7
+ module UDPProxy
8
+ def self.start(ip, port, relay_ip, relay_port)
9
+ start_logger
10
+
11
+ EM::run do
12
+ Syslog.notice "Starting proxy on: #{ip}:#{port}"
13
+ EM::open_datagram_socket ip, port, UDPProxy::Server, ip, relay_ip, relay_port
14
+ trap("TERM") { stop }
15
+ trap("INT") { stop }
16
+ end
17
+ end
18
+
19
+ def self.stop
20
+ Syslog.warning "Stopping proxy..."
21
+ EventMachine.stop
22
+ end
23
+
24
+ private
25
+ def self.start_logger
26
+ Syslog.open('UDP-Proxy')
27
+ end
28
+ end
29
+
30
+ # UDPProxy.start "127.0.0.1", 50001, "127.0.0.1", 50000
@@ -0,0 +1,39 @@
1
+ # TODO: periodically kill all dead connections
2
+ module UDPProxy
3
+ class Client < EM::Connection
4
+ attr_accessor :client_ip, :client_port
5
+
6
+ def initialize(client_ip, client_port, server)
7
+ @client_ip, @client_port = client_ip, client_port
8
+ @server = server
9
+ end
10
+
11
+ def receive_data(data)
12
+ port, ip = Socket.unpack_sockaddr_in(get_peername)
13
+ @server.send_datagram(data, client_ip, client_port)
14
+ end
15
+ end
16
+
17
+ class Clients
18
+ def initialize(server, address)
19
+ @address = address
20
+ @clients = {}
21
+ @server = server
22
+ end
23
+
24
+ def client(ip, port)
25
+ @clients[key(ip, port)] || @clients[key(ip,port)] = create_client(ip, port)
26
+ end
27
+
28
+ private
29
+ def key(ip, port)
30
+ "#{ip}:#{port}"
31
+ end
32
+
33
+ def create_client(ip, port)
34
+ Syslog.notice "Creating new client for #{ip}:#{port}"
35
+ client = EM::open_datagram_socket @address, 0, Client, ip, port, @server
36
+ end
37
+ end
38
+
39
+ end
@@ -0,0 +1,14 @@
1
+ module UDPProxy
2
+ class Server < EM::Connection
3
+ def initialize(address, relay_ip, relay_port)
4
+ @relay_ip, @relay_port = relay_ip, relay_port
5
+ @clients = Clients.new(self, address)
6
+ end
7
+
8
+ def receive_data(data)
9
+ port, ip = Socket.unpack_sockaddr_in(get_peername)
10
+ client = @clients.client(ip, port)
11
+ client.send_datagram(data, @relay_ip, @relay_port)
12
+ end
13
+ end
14
+ end
metadata ADDED
@@ -0,0 +1,73 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: em-udp-proxy
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.1.0
6
+ platform: ruby
7
+ authors:
8
+ - Arik Fraimovich
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2012-03-06 00:00:00 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: eventmachine
17
+ prerelease: false
18
+ requirement: &id001 !ruby/object:Gem::Requirement
19
+ none: false
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ type: :runtime
25
+ version_requirements: *id001
26
+ description: EventMachine UDP Proxy
27
+ email:
28
+ - arik@arikfr.com
29
+ executables:
30
+ - em-udp-proxy
31
+ extensions: []
32
+
33
+ extra_rdoc_files: []
34
+
35
+ files:
36
+ - .gitignore
37
+ - Gemfile
38
+ - README
39
+ - Rakefile
40
+ - bin/em-udp-proxy
41
+ - em-udp-proxy.gemspec
42
+ - lib/udp_proxy.rb
43
+ - lib/udp_proxy/client.rb
44
+ - lib/udp_proxy/server.rb
45
+ homepage: http://github.com/arikfr/em-udp-proxy
46
+ licenses: []
47
+
48
+ post_install_message:
49
+ rdoc_options: []
50
+
51
+ require_paths:
52
+ - lib
53
+ required_ruby_version: !ruby/object:Gem::Requirement
54
+ none: false
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ version: "0"
59
+ required_rubygems_version: !ruby/object:Gem::Requirement
60
+ none: false
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ version: "0"
65
+ requirements: []
66
+
67
+ rubyforge_project:
68
+ rubygems_version: 1.8.10
69
+ signing_key:
70
+ specification_version: 3
71
+ summary: EventMachine UDP Proxy
72
+ test_files: []
73
+