Class: VpnRoutingMac::Config

Inherits:
Object
  • Object
show all
Defined in:
lib/vpn_routing_mac/config.rb

Defined Under Namespace

Classes: DirectoryNameNotFoundError, InterfaceNotFoundError

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(params, dir_path: nil, interface: nil) ⇒ Config




82
83
84
85
86
# File 'lib/vpn_routing_mac/config.rb', line 82

def initialize(params, dir_path: nil, interface: nil)
  @gateway_ip = params["gateway_ip"]
  @interface = interface
  @dir_path = dir_path
end

Instance Attribute Details

#dir_pathObject (readonly)

Returns the value of attribute dir_path.



9
10
11
# File 'lib/vpn_routing_mac/config.rb', line 9

def dir_path
  @dir_path
end

#gateway_ipObject (readonly)

Returns the value of attribute gateway_ip.



8
9
10
# File 'lib/vpn_routing_mac/config.rb', line 8

def gateway_ip
  @gateway_ip
end

#interface(gateway_ip = @gateway_ip) ⇒ Object

Returns the value of attribute interface.



10
11
12
# File 'lib/vpn_routing_mac/config.rb', line 10

def interface
  @interface
end

Class Method Details

.active_configsArray<VpnRoutingMac::Config>

configs in active connection

Returns:



28
29
30
# File 'lib/vpn_routing_mac/config.rb', line 28

def self.active_configs
  all_configs.select(&:active_connection?)
end

.all_configsArray<VpnRoutingMac::Config>

Returns:



33
34
35
36
37
38
39
40
41
42
# File 'lib/vpn_routing_mac/config.rb', line 33

def self.all_configs
  config_files = config_dir.glob("config/*/config.yml")

  return [] if config_files.count == 0

  config_files.map { |config_file|
    params = YAML.load_file(config_file)
    self.new(params, dir_path: config_file.dirname)
  }
end

.config_dirObject



44
45
46
47
48
49
50
# File 'lib/vpn_routing_mac/config.rb', line 44

def self.config_dir
  if ENV.include?("HOME")
    home_config_dir
  else
    etc_config_dir
  end
end

.create_config_directory(dir:, gateway_ip:) ⇒ Pathname

Returns created dir path.

Returns:

  • (Pathname)

    created dir path



61
62
63
64
65
66
67
68
69
70
71
# File 'lib/vpn_routing_mac/config.rb', line 61

def self.create_config_directory(dir:, gateway_ip:)
  new_config_dir = home_config_dir.join("config/#{dir}")
  new_config_dir.mkpath
  new_config_dir.join("config.yml").write({
    gateway_ip: gateway_ip
  })
  new_config_dir.join("ip_addresses").mkdir
  new_config_dir.join("domains").mkdir

  new_config_dir
end

.etc_config_dirObject



56
57
58
# File 'lib/vpn_routing_mac/config.rb', line 56

def self.etc_config_dir
  Pathname.new("/etc/ppp/config")
end

.find_with_directory_name(dirname) ⇒ VpnRoutingMac::Config



18
19
20
21
22
23
# File 'lib/vpn_routing_mac/config.rb', line 18

def self.find_with_directory_name(dirname)
  config = all_configs.find { |a| a.directory_name == dirname }
  raise DirectoryNameNotFoundError.new(dirname) if config.nil?

  config
end

.home_config_dirObject



52
53
54
# File 'lib/vpn_routing_mac/config.rb', line 52

def self.home_config_dir
  Pathname.new("#{ENV.fetch("HOME")}/.vpn-routing")
end

.load_with_ip(ip_address) ⇒ VpnRoutingMac::Config?

Returns:



13
14
15
# File 'lib/vpn_routing_mac/config.rb', line 13

def self.load_with_ip(ip_address)
  all_configs.find { |a| a.gateway_ip == ip_address }
end

.search_ip_with_domain(domain) ⇒ Array<String>

Returns:

  • (Array<String>)


74
75
76
77
78
# File 'lib/vpn_routing_mac/config.rb', line 74

def self.search_ip_with_domain(domain)
  CommandExecutor.instance.execute!("/usr/bin/dig +short #{domain}").lines.map(&:strip).select { |a|
    /\A\d+\.\d+\.\d+\.\d+\z/.match?(a)
  }.map { |ip| "#{ip}/32" }
end

Instance Method Details

#active_connection?(gateway_ip = @gateway_ip) ⇒ Boolean

Returns:

  • (Boolean)


158
159
160
# File 'lib/vpn_routing_mac/config.rb', line 158

def active_connection?(gateway_ip = @gateway_ip)
  fetch_interface(gateway_ip)
end

#all_interfacesObject



162
163
164
# File 'lib/vpn_routing_mac/config.rb', line 162

def all_interfaces
  @all_interfaces ||= CommandExecutor.instance.execute!("/sbin/ifconfig -l").strip.split(" ")
end

#all_ip_addressesArray<String>

#domains + #ip_addresses

Returns:

  • (Array<String>)
    “192.168.1.1/32”


115
116
117
118
119
# File 'lib/vpn_routing_mac/config.rb', line 115

def all_ip_addresses
  (domains.map { |domain|
    self.class.search_ip_with_domain(domain)
  }.flatten + ip_addresses).uniq
end

#delete_route!(ip_address, interface: nil) ⇒ Object



139
140
141
142
143
144
145
# File 'lib/vpn_routing_mac/config.rb', line 139

def delete_route!(ip_address, interface: nil)
  interface ||= self.interface

  raise InterfaceNotFoundError.new(interface) unless interface_exist?(interface)

  CommandExecutor.instance.execute!("/sbin/route delete -net #{ip_address} -interface #{interface}")
end

#directory_nameObject



88
89
90
# File 'lib/vpn_routing_mac/config.rb', line 88

def directory_name
  @dir_path.basename.to_s
end

#domainsArray<String>

Returns [“example.test”].

Returns:

  • (Array<String>)
    “example.test”


93
94
95
96
97
98
99
100
# File 'lib/vpn_routing_mac/config.rb', line 93

def domains
  file_paths = dir_path.glob("domains/*")
  return [] if file_paths.count == 0

  # e.g.
  #   example.test # The example domain
  file_paths.map { |f| f.read.lines.map { |a| a.strip.split("#").first } }.flatten
end

#fetch_interface(gateway_ip) ⇒ Object

Parameters:

  • gateway_ip (String)

    192.168.1.1



152
153
154
155
156
# File 'lib/vpn_routing_mac/config.rb', line 152

def fetch_interface(gateway_ip)
  all_interfaces.find { |a|
    CommandExecutor.instance.execute!("/sbin/ifconfig #{a} | grep #{gateway_ip}") rescue false
  }
end

#interface_exist?(interface) ⇒ Boolean

Returns:

  • (Boolean)


166
167
168
# File 'lib/vpn_routing_mac/config.rb', line 166

def interface_exist?(interface)
  all_interfaces.include?(interface)
end

#ip_addressesArray<String>

Returns [“192.168.1.1/32”].

Returns:

  • (Array<String>)
    “192.168.1.1/32”


103
104
105
106
107
108
109
110
# File 'lib/vpn_routing_mac/config.rb', line 103

def ip_addresses
  file_paths = dir_path.glob("ip_addresses/*")
  return [] if file_paths.count == 0

  # e.g.
  #   192.168.1.1/32 # local ip
  file_paths.map { |f| f.read.lines.map { |a| a.strip.split("#").first } }.flatten
end

#route!(ip_address, interface: nil) ⇒ Object

set routing require: MacOS catalina or later.

Parameters:

  • ip_address (String)

    “192.168.191.0/32”

Raises:



125
126
127
128
129
130
131
# File 'lib/vpn_routing_mac/config.rb', line 125

def route!(ip_address, interface: nil)
  interface ||= self.interface

  raise InterfaceNotFoundError.new(interface) unless interface_exist?(interface)

  CommandExecutor.instance.execute!("/sbin/route add -net #{ip_address} -interface #{interface}")
end

#route_all!Object



133
134
135
136
137
# File 'lib/vpn_routing_mac/config.rb', line 133

def route_all!
  all_ip_addresses.map(&:to_s).map(&:strip).select { |a| %r;\A\d+\.\d+\.\d+\.\d+(/\d+)?\z;.match?(a) }.each do |ip_address|
    route!(ip_address)
  end
end

#save_domain!(domain, comment) ⇒ Object



181
182
183
184
185
186
187
188
189
# File 'lib/vpn_routing_mac/config.rb', line 181

def save_domain!(domain, comment)
  cli_config_path = @dir_path.join("domains/cli.txt")
  cli_config_path.open("a") do |f|
    f.puts "#{domain} # #{comment}"
  end

  user = ENV.fetch("USER")
  CommandExecutor.instance.execute!("chown #{user} #{cli_config_path.to_s}")
end

#save_ip_address!(ip_address, comment) ⇒ Object



170
171
172
173
174
175
176
177
178
179
# File 'lib/vpn_routing_mac/config.rb', line 170

def save_ip_address!(ip_address, comment)
  cli_config_path = @dir_path.join("ip_addresses/cli.txt")
  cli_config_path.open("a") do |f|
    f.puts "#{ip_address} # #{comment}"
  end

  user = ENV.fetch("USER")

  CommandExecutor.instance.execute!("chown #{user} #{cli_config_path.to_s}")
end