Tinc setup

This commit is contained in:
Paul-Henri Froidmont 2018-09-18 04:00:12 +02:00
parent 3bcd961c81
commit e954247db5
20 changed files with 584 additions and 59 deletions

View file

@ -0,0 +1,2 @@
---
- debug: msg="Not Implemented"

View file

@ -0,0 +1,74 @@
---
- name: Get the internet interface
shell: ip route get 1.1.1.1 | head -n1 | sed -E 's/^.+dev ([^ ]+).+$/\1/'
register: interface_result
changed_when: False
check_mode: False
- name: Check for internet access
shell: |-
false \{% for url in proxy_test_urls %}
|| curl -IsSL -m{{ proxy_test_timeout }} {{ url }} \
{% endfor %}
|| false
args:
warn: False
register: curl_result_initial
ignore_errors: True
changed_when: False
check_mode: False
- name: Set host interface facts
set_fact:
proxy_interface: "{{ interface_result.stdout | trim }}"
proxy_inet: "{{ curl_result_initial.rc == 0 }}"
- name: Assert at least one node has internet connectivity
assert:
that: hostvars.values() | selectattr('inventory_hostname', 'in', groups['k8s']) | selectattr('proxy_inet', '==', True) | list | length != 0
run_once: true
- name: Set router hostname fact
set_fact:
proxy_router_hostname: "{{ hostvars.values() | selectattr('inventory_hostname', 'in', groups['k8s']) | selectattr('proxy_inet', '==', True) | map(attribute='inventory_hostname') | first }}"
- name: Allow ip forwarding (kernel)
sysctl:
name: net.ipv4.ip_forward
value: 1
sysctl_set: True
reload: True
- name: Allow ip forwarding (iptables)
iptables:
table: nat
chain: POSTROUTING
out_interface: "{{ proxy_interface }}"
jump: MASQUERADE
register: iptables_result
- name: Set up SSH tunnels
include: ssh-up.yml
when: hostvars.values() | selectattr('inventory_hostname', 'in', groups['k8s']) | selectattr('proxy_inet', '==', False) | list | length != 0
- name: Set up tinc
include_role:
name: tinc
- name: Set up keepalived
include: keepalived.yml
- name: Tear down SSH tunnels
include: ssh-down.yml
- name: Check for internet access
shell: |-
false \{% for url in proxy_test_urls %}
|| curl -IsSL -m{{ proxy_test_timeout }} {{ url }} \
{% endfor %}
|| false
args:
warn: False
register: curl_result
changed_when: curl_result_initial.rc != curl_result.rc
check_mode: False

View file

@ -0,0 +1,52 @@
---
- name: Kill existing tunnel connections
shell: |
CONNECTION_PIDS=$(ps aux | awk '$1 == "{{ proxy_ssh_user }}" && $0 ~ /ssh -N -f/ { print $2 }')
echo $CONNECTION_PIDS | xargs -r kill
echo "$CONNECTION_PIDS" | grep -vE '^$' | wc -l
register: ssh_result
changed_when: ssh_result.stdout_lines | last | int > 0
- name: Remove tunnel interfaces
shell:
cmd: |
bash -s <<'EOF'
TUN_INTERFACE_FILES=$(grep -El '^## sshproxy' /etc/network/interfaces.d/tun*)
IFS=$'\n\t'
for file in $TUN_INTERFACE_FILES; do
interface=$(basename $file)
echo $interface
rm $file
ip link delete $interface
done
EOF
register: tun_result
changed_when: tun_result.stdout_lines | length > 0
- name: Remove tunnel iptables (1/2)
iptables:
state: absent
chain: FORWARD
in_interface: "{{ proxy_interface }}"
out_interface: "{{ item }}"
ctstate:
- RELATED
- ESTABLISHED
jump: ACCEPT
with_items: "{{ tun_result.stdout_lines }}"
when: inventory_hostname == proxy_router_hostname
- name: Remove tunnel iptables (2/2)
iptables:
state: absent
chain: FORWARD
in_interface: "{{ item }}"
out_interface: "{{ proxy_interface }}"
jump: ACCEPT
with_items: "{{ tun_result.stdout_lines }}"
when: inventory_hostname == proxy_router_hostname
- name: Remove authorized keys file
file:
path: "/home/{{ proxy_ssh_user }}/.ssh/authorized_keys"
state: absent

View file

@ -0,0 +1,131 @@
---
# All nodes may use the ssh proxy user to connect to any other node
# to use point-to-point tunnelling.
# remove existing interfaces in case of an error so we don't run out of ip addresses
- name: Remove existing tunnel interfaces
include: ssh-down.yml
- name: Add the proxy user
user:
name: "{{ proxy_ssh_user }}"
shell: /bin/false
- name: Allow point-to-point tunnelling for the ssh proxy user
blockinfile:
block: |
# sshproxy start
Match User {{ proxy_ssh_user }}
AllowTcpForwarding yes
PermitTunnel point-to-point
ForceCommand /bin/false
# sshproxy end
dest: "/etc/ssh/sshd_config"
validate: "/usr/sbin/sshd -T -f %s"
notify: reload sshd
- meta: flush_handlers
- name: Create ssh private key
shell: yes '' | ssh-keygen -N ''
args:
chdir: "/home/{{ proxy_ssh_user }}"
creates: "/home/{{ proxy_ssh_user }}/.ssh/id_rsa.pub"
become: True
become_method: su
become_flags: '-s /bin/sh'
become_user: "{{ proxy_ssh_user }}"
- name: Read public key
slurp:
src: "/home/{{ proxy_ssh_user }}/.ssh/id_rsa.pub"
register: public_key_result
- name: Set public key fact
set_fact:
proxy_ssh_public_key: "{{ public_key_result.content | b64decode | trim }}"
- block:
- name: Set authorized keys
authorized_key:
user: "{{ proxy_ssh_user }}"
key: "{{ item }}"
with_items: "{{ hostvars.values() | selectattr('inventory_hostname', 'in', groups['k8s']) | selectattr('proxy_ssh_public_key', 'defined') | map(attribute='proxy_ssh_public_key') | list }}"
- name: Create tunnel interfaces on the router host
shell:
cmd: |
bash -s <<'EOF'
{{ lookup('template', './tunnel.j2') }}
EOF
register: tun_result
with_items: "{{ hostvars.values() | selectattr('inventory_hostname', 'in', groups['k8s']) | selectattr('proxy_inet', '==', False) | map(attribute='inventory_hostname') | list }}"
- name: Set created interfaces fact
set_fact:
proxy_ssh_tunnel_map: "{{ tun_result.results | map(attribute='stdout') | map('from_json') | list }}"
- name: Add tunnel iptables (1/2)
iptables:
chain: FORWARD
in_interface: "{{ proxy_interface }}"
out_interface: "{{ item.interface }}"
ctstate:
- RELATED
- ESTABLISHED
jump: ACCEPT
with_items: "{{ proxy_ssh_tunnel_map }}"
- name: Add tunnel iptables (2/2)
iptables:
chain: FORWARD
in_interface: "{{ item.interface }}"
out_interface: "{{ proxy_interface }}"
jump: ACCEPT
with_items: "{{ proxy_ssh_tunnel_map }}"
when: inventory_hostname == proxy_router_hostname
- block:
- set_fact: proxy_target="{{ ( hostvars[proxy_router_hostname].proxy_ssh_tunnel_map | selectattr('target_hostname', '==', inventory_hostname) | list )[0] }}"
- block:
- shell: "ip route get 169.254.42.42 | head -n1 | sed -E 's/.+ dev ([^ ]+).+/\\1/'"
register: result
- set_fact: proxy_private_interface="{{ result.stdout }}"
when: proxy_private_interface | length == 0
# TODO edit /etc/network/interfaces (?) to apply rules on network up
- name: Create tunnel interface on the target hosts
shell:
cmd: |
bash -s <<'EOF'
echo "## sshproxy" > /etc/network/interfaces.d/{{ proxy_target.interface }}
ip tuntap add mode tun dev {{ proxy_target.interface }}
ip addr add {{ proxy_target.target_ip }}/30 peer {{ proxy_target.router_ip }} dev {{ proxy_target.interface }}
ip link set dev {{ proxy_target.interface }} up
DEFAULT_GATEWAY=$(ip route | awk '$3 == "{{ proxy_private_interface }}" { print $1 }' | cut -d'/' -f1)
ip route add 10.0.0.0/8 via $DEFAULT_GATEWAY dev {{ proxy_private_interface }}
ip route add 169.254.0.0/16 via $DEFAULT_GATEWAY dev {{ proxy_private_interface }}
ip route add 172.16.0.0/12 via $DEFAULT_GATEWAY dev {{ proxy_private_interface }}
ip route add 192.168.0.0/16 via $DEFAULT_GATEWAY dev {{ proxy_private_interface }}
ip route replace default via {{ proxy_target.target_ip }}
EOF
- name: Establish the SSH tunnel
shell: |
ssh -N -f \
-w {{ proxy_target.interface_id }}:{{ proxy_target.interface_id }} \
-o StrictHostKeyChecking=no \
-o UserKnownHostsFile=/dev/null \
{{ hostvars[proxy_router_hostname]['ansible_' + proxy_private_interface].ipv4.address }} &
echo $!
become: True
become_method: su
become_flags: '-s /bin/sh'
become_user: "{{ proxy_ssh_user }}"
when: inventory_hostname in hostvars[proxy_router_hostname].proxy_ssh_tunnel_map | map(attribute='target_hostname') | list