diff options
| author | Paul Buetow <paul@buetow.org> | 2025-04-18 23:53:53 +0300 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2025-04-18 23:53:53 +0300 |
| commit | 799c111fb47e03b693074374210c8c9c938bc8e7 (patch) | |
| tree | bf166ea93c9515f10de92a2a832ee8fe7ad41b2c | |
| parent | 5e4208c5c3014f96bd2d6804ddad8df6907dc7cf (diff) | |
can generate keys
| -rw-r--r-- | .gitignore | 1 | ||||
| -rw-r--r-- | wireguardmeshgenerator.rb | 82 |
2 files changed, 61 insertions, 22 deletions
@@ -1 +1,2 @@ dist/ +keys/ diff --git a/wireguardmeshgenerator.rb b/wireguardmeshgenerator.rb index ae7ddd4..2a76e73 100644 --- a/wireguardmeshgenerator.rb +++ b/wireguardmeshgenerator.rb @@ -1,7 +1,8 @@ -#!/usr/bin/ruby +#!/usr/bin/env ruby require 'fileutils' +WIREGUARD_TOOL = '/usr/bin/wg'.freeze HOSTS = { f0: { lan: { domain: 'lan.buetow.org', ip: '192.168.1.130' }, wg0: { domain: 'wg0.buetow.org', ip: '192.168.2.130' } }, @@ -17,45 +18,82 @@ HOSTS = { wg0: { domain: 'wg0.buetow.org', ip: '192.168.2.122' } } }.freeze -PeerSnippet = Struct.new(:description, :public_key, :preshared_key, :allowed_ips) do +# Generates Wireguard keys and config files for each host +class KeyTool + def initialize(myself) + keys_dir = "keys/#{myself}/" + FileUtils.mkdir_p(keys_dir) unless Dir.exist?(keys_dir) + + @pubkey_path = "#{keys_dir}/pubkey" + @privkey_path = "#{keys_dir}/privkey" + @preshared_path = "#{keys_dir}/preshared" + + generate! if !File.exist?(@pubkey_path) || + !File.exist?(@privkey_path) || + !File.exist?(@preshared_path) + end + + def pub = File.read(@pubkey_path).strip + def priv = File.read(@privkey_path).strip + def preshared = File.read(@preshared_path).strip + + private + + def generate! = gen_privpub! && genpsk! + def genpsk! = File.write(@preshared_path, `#{WIREGUARD_TOOL} genpsk`) + + def gen_privpub! + privkey = IO.popen("#{WIREGUARD_TOOL} genkey", 'r+', &:read) + IO.popen("#{WIREGUARD_TOOL} pubkey", 'r+') do |io| + io.puts(privkey) + io.close_write + File.write(@privkey_path, privkey) + File.write(@pubkey_path, io.read) + end + end +end + +PeerSnippet = Struct.new(:myself, :domain, :allowed_ips) do def to_s + keys = KeyTool.new(myself) <<~PEER_CONFIG [Peer] - # #{description} - PublicKey = #{public_key} - PresharedKey = #{preshared_key} - AllowedIPs = #{allowed_ips} + # #{myself}.#{domain} + PublicKey = #{keys.pub} + PresharedKey = #{keys.preshared} + AllowedIPs = #{allowed_ips}/32 PEER_CONFIG end end WireguardConfig = Struct.new(:myself, :hosts) do - @peers = hosts.map do |name, data| - PeerSnippet.new("#{name}.#{data[:wg0][:domain]}", - :PUB_KEY, :PRESHARED_KEY, "#{data[:wg0][:ip]}/32") - end - def to_s + peers = hosts.reject { _1 == myself }.map do |hostname, data| + PeerSnippet.new(hostname, data[:wg0][:domain], data[:wg0][:ip]) + end + + keys = KeyTool.new(myself) <<~CONFIG [Interface] + # #{myself}.#{hosts[myself][:wg0][:domain]} Address = #{hosts[myself][:wg0][:ip]} - PrivateKey = #{private_key} + PrivateKey = #{keys.priv} + PresharedKey = #{keys.preshared} - #{@peers.map(&:to_s).join("\n")} + #{peers.map(&:to_s).join("\n")} CONFIG end - - private - - def private_key = 'PRIVATE_KEY' end -HOSTS.each_key do |name| - config_dir = "dist/#{name}/etc/wireguard" +HOSTS.each_key do |hostname| + raise 'Wireguard tool not found' unless File.exist?(WIREGUARD_TOOL) + + config_dir = "dist/#{hostname}/etc/wireguard" + key_dir = "keys/#{hostname}/" config_path = "#{config_dir}/wg0.conf" - FileUtils.mkdir_p(config_dir) unless Dir.exist?(config_dir) + [config_dir, key_dir].each { FileUtils.mkdir_p(_1) unless Dir.exist?(_1) } - wg0 = WireguardConfig.new(name, HOSTS) - puts "Generating config for #{name} at #{config_path}" + wg0 = WireguardConfig.new(hostname, HOSTS) + puts "Generating config for #{hostname} at #{config_path}" File.write(config_path, wg0.to_s) end |
