#!/usr/bin/env bash
set -Eeuo pipefail

# Install BleachWrt/OpenWrt in Docker on CentOS 7 with a macvlan network.
# This helper only deploys the base container and LAN networking. It does not
# install, import, or configure proxy, tunneling, bypass, or traffic evasion rules.

SCRIPT_NAME="install_bleachwrt_docker_centos7.sh"
INSTALL_DIR="${INSTALL_DIR:-/opt/bleachwrt}"
CONTAINER_NAME="${CONTAINER_NAME:-bleachwrt}"
IMAGE="${IMAGE:-bleachwrt/mini:latest}"
CONTAINER_IP="${CONTAINER_IP:-192.168.30.11}"
SUBNET="${SUBNET:-192.168.30.0/24}"
GATEWAY="${GATEWAY:-192.168.30.1}"
SHIM_IP="${SHIM_IP:-192.168.30.200}"
NETWORK_NAME="${NETWORK_NAME:-bleachwrt_macvlan}"
YES=0
INSTALL_DOCKER=1

red() { printf '\033[0;31m%s\033[0m\n' "$*"; }
green() { printf '\033[0;32m%s\033[0m\n' "$*"; }
yellow() { printf '\033[1;33m%s\033[0m\n' "$*"; }
blue() { printf '\033[0;36m%s\033[0m\n' "$*"; }
die() { red "[ERROR] $*"; exit 1; }
info() { blue "[INFO] $*"; }
ok() { green "[OK] $*"; }
warn() { yellow "[WARN] $*"; }

usage() {
  cat <<USAGE
Usage:
  sudo bash ${SCRIPT_NAME} [--yes] [--no-install-docker]

Environment variables:
  IFACE=enp2s0
  CONTAINER_IP=192.168.30.11
  SUBNET=192.168.30.0/24
  GATEWAY=192.168.30.1
  SHIM_IP=192.168.30.200
  IMAGE=bleachwrt/mini:latest
  INSTALL_DIR=/opt/bleachwrt

Example:
  curl -fsSL https://helper.sh/install_bleachwrt_docker_centos7.sh | sudo bash -s -- --yes

Compliance scope:
  This script deploys a local OpenWrt-compatible container for lawful LAN use.
  It does not configure Passwall, Shadowsocks, NaiveProxy, VPN bypass, or any
  other traffic circumvention feature.
USAGE
}

while [ "$#" -gt 0 ]; do
  case "$1" in
    -y|--yes) YES=1 ;;
    --no-install-docker) INSTALL_DOCKER=0 ;;
    -h|--help) usage; exit 0 ;;
    *) die "Unknown argument: $1" ;;
  esac
  shift
done

[ "$(id -u)" -eq 0 ] || die "Run as root or with sudo."

if [ -r /etc/centos-release ]; then
  if ! grep -Eq 'CentOS Linux release 7|CentOS release 7' /etc/centos-release; then
    warn "This script is designed for CentOS 7. Current release: $(cat /etc/centos-release)"
  fi
else
  warn "/etc/centos-release was not found. Continuing because this may be a compatible host."
fi

detect_iface() {
  ip route show default 2>/dev/null | awk 'NR == 1 { print $5 }'
}

IFACE="${IFACE:-$(detect_iface)}"
[ -n "${IFACE}" ] || die "Could not detect the default network interface. Set IFACE=enp2s0 and rerun."
ip link show "${IFACE}" >/dev/null 2>&1 || die "Network interface ${IFACE} does not exist."

cat <<PLAN

${SCRIPT_NAME} will make these changes:
  - Install Docker on CentOS 7 if it is missing
  - Pull image: ${IMAGE}
  - Create Docker macvlan network: ${NETWORK_NAME}
  - Run container: ${CONTAINER_NAME} at ${CONTAINER_IP}
  - Persist OpenWrt /etc/config under: ${INSTALL_DIR}/openwrt-config
  - Create systemd service: bleachwrt.service
  - Create host macvlan shim: ${SHIM_IP}/32 for host-to-container access

It will not import local proxy/VPN/circumvention configuration.

PLAN

if [ "${YES}" -ne 1 ]; then
  printf "Continue? Type YES to proceed: "
  read -r answer
  [ "${answer}" = "YES" ] || die "Cancelled."
fi

install_docker_if_needed() {
  if command -v docker >/dev/null 2>&1; then
    ok "Docker is already installed."
    return
  fi

  [ "${INSTALL_DOCKER}" -eq 1 ] || die "Docker is missing and --no-install-docker was set."

  info "Installing Docker CE through yum."
  yum install -y yum-utils device-mapper-persistent-data lvm2
  yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
  yum install -y docker-ce docker-ce-cli containerd.io
  systemctl enable docker
}

install_docker_if_needed

mkdir -p "${INSTALL_DIR}/openwrt-config"

cat > "${INSTALL_DIR}/openwrt-config/network" <<EOF
config interface 'loopback'
        option device 'lo'
        option proto 'static'
        option ipaddr '127.0.0.1'
        option netmask '255.0.0.0'

config interface 'lan'
        option device 'eth0'
        option proto 'static'
        option ipaddr '${CONTAINER_IP}'
        option netmask '255.255.255.0'
        option gateway '${GATEWAY}'
        option dns '${GATEWAY}'
EOF

cat > "${INSTALL_DIR}/env" <<EOF
IFACE=${IFACE}
CONTAINER_IP=${CONTAINER_IP}
SUBNET=${SUBNET}
GATEWAY=${GATEWAY}
SHIM_IP=${SHIM_IP}
IMAGE=${IMAGE}
NETWORK_NAME=${NETWORK_NAME}
CONTAINER_NAME=${CONTAINER_NAME}
INSTALL_DIR=${INSTALL_DIR}
EOF

sysctl -w net.ipv4.ip_forward=1 >/dev/null
if grep -q '^net.ipv4.ip_forward' /etc/sysctl.conf; then
  sed -i 's/^net.ipv4.ip_forward.*/net.ipv4.ip_forward = 1/' /etc/sysctl.conf
else
  printf '\nnet.ipv4.ip_forward = 1\n' >> /etc/sysctl.conf
fi
ok "IPv4 forwarding is enabled."

ip link set "${IFACE}" promisc on || warn "Could not enable promiscuous mode on ${IFACE}."

cat > /etc/systemd/system/bleachwrt.service <<EOF
[Unit]
Description=BleachWrt OpenWrt Docker container with macvlan
After=network-online.target docker.service
Wants=network-online.target
Requires=docker.service

[Service]
Type=oneshot
RemainAfterExit=yes
EnvironmentFile=${INSTALL_DIR}/env
ExecStartPre=-/usr/bin/docker rm -f \${CONTAINER_NAME}
ExecStartPre=-/usr/bin/docker network rm \${NETWORK_NAME}
ExecStartPre=/usr/bin/docker network create -d macvlan --subnet=\${SUBNET} --gateway=\${GATEWAY} -o parent=\${IFACE} \${NETWORK_NAME}
ExecStartPre=/usr/bin/docker pull \${IMAGE}
ExecStart=/bin/bash -c '/usr/bin/docker run -d --name "\${CONTAINER_NAME}" --restart unless-stopped --privileged --network "\${NETWORK_NAME}" --ip "\${CONTAINER_IP}" -v "\${INSTALL_DIR}/openwrt-config:/etc/config" "\${IMAGE}"; ip link add macvlan-shim link "\${IFACE}" type macvlan mode bridge 2>/dev/null || true; ip addr add "\${SHIM_IP}/32" dev macvlan-shim 2>/dev/null || true; ip link set macvlan-shim up; ip route add "\${CONTAINER_IP}/32" dev macvlan-shim 2>/dev/null || true'
ExecStop=/bin/bash -c 'ip link delete macvlan-shim 2>/dev/null || true; /usr/bin/docker rm -f "\${CONTAINER_NAME}" 2>/dev/null || true; /usr/bin/docker network rm "\${NETWORK_NAME}" 2>/dev/null || true'
TimeoutStartSec=180
TimeoutStopSec=30

[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
systemctl enable docker
systemctl restart docker
systemctl enable bleachwrt.service
systemctl restart bleachwrt.service

sleep 8

if docker ps --format '{{.Names}}' | grep -qx "${CONTAINER_NAME}"; then
  ok "Container ${CONTAINER_NAME} is running."
else
  systemctl status bleachwrt.service --no-pager || true
  die "Container ${CONTAINER_NAME} is not running."
fi

docker exec "${CONTAINER_NAME}" /etc/init.d/network restart >/dev/null 2>&1 || true

cat <<DONE

Install complete.

LAN management URL:
  http://${CONTAINER_IP}/

Operational commands:
  systemctl status bleachwrt
  systemctl restart bleachwrt
  systemctl stop bleachwrt
  docker logs ${CONTAINER_NAME}

Ports and firewall scope:
  - Docker macvlan gives the container its own LAN IP. This script does not publish host ports with -p.
  - For basic web management, allow LAN clients to reach ${CONTAINER_IP}:80/tcp.
  - Open ${CONTAINER_IP}:443/tcp only if the image enables HTTPS management.
  - Open ${CONTAINER_IP}:22/tcp only if you intentionally enable SSH on the OpenWrt container.
  - Open DNS/DHCP ports only when you intentionally use this container for those LAN services:
    53/tcp, 53/udp, 67/udp, 68/udp.
  - Do not expose these ports to the public internet.

Created paths:
  ${INSTALL_DIR}/
  ${INSTALL_DIR}/env
  ${INSTALL_DIR}/openwrt-config/
  ${INSTALL_DIR}/openwrt-config/network
  /etc/systemd/system/bleachwrt.service

Security notes:
  - Keep the management URL on a trusted LAN only.
  - Change the OpenWrt root password immediately after first login.
  - Review the image source and license before production use.
  - This script intentionally did not import proxy, VPN bypass, or circumvention config.

DONE
