Skip to content

VPS for egress port testing

Objective

Use a cloud service to run a server that will answer on all TCP ports.

Most of the steps are taken from http://portquiz.net (http://positon.org/portquiz-net-how-it-works) which is the service that I have been using previously.

Configuration

Use the following Ansible playbook to configure the host.

In summary, the playbook will install a web server (caddy) and configure iptables to forward all TCP ports to the web server (port 80/TCP).

yaml
###
---
- name: Configure a host to answer all TCP requests
  hosts: localhost
  connection: local
  become: true

  tasks:
    - name: Install packages
      ansible.builtin.apt:
        name: "{{ item }}"
        state: present
        update_cache: true
      loop:
        - iptables-persistent
        - caddy

    - name: Remove default configuration files
      ansible.builtin.file:
        path: "{{ item }}"
        state: absent
        force: true
      loop:
        - /etc/caddy/Caddyfile
        - /etc/iptables/rules.v4

    - name: Configure web server
      ansible.builtin.blockinfile:
        path: /etc/caddy/Caddyfile
        create: true
        block: |
          :80 {
            respond "GoSecure - open - {remote_host}" 418
          }
        owner: root
        group: root
        mode: 0644
      register: web_server

    - name: Configure iptables rules
      ansible.builtin.blockinfile:
        path: /etc/iptables/rules.v4
        create: true
        block: |
          *nat
          :PREROUTING ACCEPT [0:0]
          :POSTROUTING ACCEPT [0:0]
          :OUTPUT ACCEPT [0:0]
          -A PREROUTING -i lo -j RETURN
          -A PREROUTING -p icmp -j RETURN
          -A PREROUTING -m state --state RELATED,ESTABLISHED -j RETURN
          -A PREROUTING -p tcp -m tcp --dport 22 -j RETURN
          -A PREROUTING -p tcp -m tcp --dport 80 -j RETURN
          -A PREROUTING -p tcp -j DNAT --to-destination :80
          COMMIT
          *filter
          :INPUT ACCEPT [0:0]
          :FORWARD ACCEPT [0:0]
          :OUTPUT ACCEPT [0:0]
          -A INPUT -p icmp -j ACCEPT
          -A INPUT -i lo -j ACCEPT
          -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
          -A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
          -A INPUT -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT
          -A INPUT -j DROP
          COMMIT
        owner: root
        group: root
        mode: 0644
      register: iptables_rules

    - name: Restart iptables service
      ansible.builtin.systemd_service:
        name: iptables
        state: restarted
      when: iptables_rules is changed

    - name: Restart web service service
      ansible.builtin.systemd_service:
        name: caddy
        state: restarted
      when: web_server is changed

There are a few ways to go about running the above playbook. You could create a public repo with the above playbook in it and run it with:

bash
# apt install ansible
# ansible-pull -U http://git.incus/chris/ansible-pull playbook.yml

Another way would be to save the playbook somewhere (VCS, web server, etc.) and fetch the file, and then run it.

bash
# apt install ansible curl
# curl -O http://REMOTE_WEB_SERVER/playbook.yml
# ansible-playbook playbook.yml

AWS

It is also possible to pass a script to AWS user data under EC2 Advanced Options

bash
#!/bin/bash
export DEBIAN_FRONTEND=noninteractive
apt update
apt install -y ansible
cat << EOF > /root/playbook.yml
---
- name: Configure a host to answer all TCP requests
  hosts: localhost
  connection: local
  become: true

  tasks:
    - name: Install packages
      ansible.builtin.apt:
        name: "{{ item }}"
        state: present
        update_cache: true
      loop:
        - iptables-persistent
        - caddy

    - name: Remove default configuration files
      ansible.builtin.file:
        path: "{{ item }}"
        state: absent
        force: true
      loop:
        - /etc/caddy/Caddyfile
        - /etc/iptables/rules.v4

    - name: Configure web server
      ansible.builtin.blockinfile:
        path: /etc/caddy/Caddyfile
        create: true
        block: |
          :80 {
            respond "GoSecure - open - {remote_host}" 418
          }
        owner: root
        group: root
        mode: 0644
      register: web_server

    - name: Configure iptables rules
      ansible.builtin.blockinfile:
        path: /etc/iptables/rules.v4
        create: true
        block: |
          *nat
          :PREROUTING ACCEPT [0:0]
          :POSTROUTING ACCEPT [0:0]
          :OUTPUT ACCEPT [0:0]
          -A PREROUTING -i lo -j RETURN
          -A PREROUTING -p icmp -j RETURN
          -A PREROUTING -m state --state RELATED,ESTABLISHED -j RETURN
          -A PREROUTING -p tcp -m tcp --dport 22 -j RETURN
          -A PREROUTING -p tcp -m tcp --dport 80 -j RETURN
          -A PREROUTING -p tcp -j DNAT --to-destination :80
          COMMIT
          *filter
          :INPUT ACCEPT [0:0]
          :FORWARD ACCEPT [0:0]
          :OUTPUT ACCEPT [0:0]
          -A INPUT -p icmp -j ACCEPT
          -A INPUT -i lo -j ACCEPT
          -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
          -A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
          -A INPUT -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT
          -A INPUT -j DROP
          COMMIT
        owner: root
        group: root
        mode: 0644
      register: iptables_rules

    - name: Restart iptables service
      ansible.builtin.systemd_service:
        name: iptables
        state: restarted
      when: iptables_rules is changed

    - name: Restart web service service
      ansible.builtin.systemd_service:
        name: caddy
        state: restarted
      when: web_server is changed

EOF
ansible-playbook /root/playbook.yml