123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281 |
- #!/bin/bash
- # Port forward script
- # acetone at mail.i2p
- # 2022
- # CONSTANTS
- INPUT_INTERFACE="changeme"
- OUTPUT_INTERFACE="changeme"
- SETTINGS_STORAGE="/srv/portforward.txt"
- ######################
- ######################
- # LOGIC
- RULES=() # inport,dest_addr,dest_port
- usage() {
- echo "PORT FORWARD SCRIPT (v0.0.1) USAGE ◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤"
- echo "--command--arguments------------------description----------"
- echo ""
- echo "* add <inport> <address> <port> Add rule to forward"
- echo " ﹂example:"
- echo " add 80 192.168.1.3 8080"
- echo " ^ ^ ^ destination port"
- echo " | └ destination address"
- echo " └ inport"
- echo ""
- echo "* del <address> <port> Delete existed rule"
- echo " ﹂example:"
- echo " del 80 192.168.1.3 8080"
- echo " ^ ^ ^ destination port"
- echo " | └ destination address"
- echo " └ inport"
- echo ""
- echo "* list Display existed rules"
- echo ""
- echo "* init Apply rules at start"
- echo ""
- echo "* install Install at first time"
- echo ""
- echo "◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤"
- }
- message_about_interfaces() {
- echo "Please edit first lines of script to define interfaces correctly"
- echo "Script path: nano /usr/sbin/port-forward.sh"
- }
- check_interface() {
- if [[ $(ip a | grep $INPUT_INTERFACE) == "" ]]; then
- echo "Input interface $INPUT_INTERFACE not exists"
- message_about_interfaces
- exit
- fi
- if [[ $(ip a | grep $OUTPUT_INTERFACE) == "" ]]; then
- echo "Output interface $OUTPUT_INTERFACE not exists"
- message_about_interfaces
- exit
- fi
- }
- check_to_root() {
- if [ "$EUID" -ne 0 ]; then
- echo "Please run as root"
- exit 1
- fi
- }
- in_port() {
- echo $1 | cut -f1 -d,
- }
- dest_address() {
- echo $1 | cut -f2 -d,
- }
- dest_port() {
- echo $1 | cut -f3 -d,
- }
- enable_forwarding() {
- check_to_root
- sed -i 's/\#net.ipv4.ip_forward=1/net.ipv4.ip_forward=1/' /etc/sysctl.conf
- sysctl net.ipv4.ip_forward=1
- sysctl -p
- systemctl stop nftables
- systemctl disable nftables
- apt update
- apt install iptables -y
- }
- add() {
- INPORT=$1
- DEST_ADDRESS=$2
- DEST_PORT=$3
- if [[ $(iptables -t nat -L -n | grep "dpt:$INPORT ") != "" ]]; then
- echo "Inport $INPORT already in use. Request rejected."
- echo "Try command 'list' to see existed rules and 'del' to remove some one."
- exit 1
- fi
- iptables -A PREROUTING -t nat -i $INPUT_INTERFACE -p tcp --dport $INPORT -j DNAT --to $DEST_ADDRESS:$DEST_PORT
- if [[ $? != 0 ]]; then
- echo "Incorrect input data"
- exit 1
- fi
- iptables -A PREROUTING -t nat -i $INPUT_INTERFACE -p udp --dport $INPORT -j DNAT --to $DEST_ADDRESS:$DEST_PORT
- echo "$INPORT,$DEST_ADDRESS,$DEST_PORT" >> $SETTINGS_STORAGE
- if [[ $(iptables -t nat -L -v | grep -e "^.*MASQUERADE.*$OUTPUT_INTERFACE.*$") == "" ]]; then
- iptables -t nat -A POSTROUTING -o $OUTPUT_INTERFACE -j MASQUERADE
- fi
- }
- del() {
- INPORT=$1
- DEST_ADDRESS=$2
- DEST_PORT=$3
- exists=false
- for rule in "${RULES[@]}"
- do
- if [[ $INPORT == $(in_port $rule) ]]; then
- if [[ $DEST_ADDRESS == $(dest_address $rule) ]]; then
- if [[ $DEST_PORT == $(dest_port $rule) ]]; then
- exists=true
- break
- fi
- fi
- fi
- done
- if [[ $exists != true ]]; then
- echo "Rule not exists"
- exit 1
- fi
- iptables -D PREROUTING -t nat -i $INPUT_INTERFACE -p tcp --dport $INPORT -j DNAT --to $DEST_ADDRESS:$DEST_PORT
- iptables -D PREROUTING -t nat -i $INPUT_INTERFACE -p udp --dport $INPORT -j DNAT --to $DEST_ADDRESS:$DEST_PORT
- sed -i "/^${INPORT},${DEST_ADDRESS},${DEST_PORT}$/d" $SETTINGS_STORAGE
- }
- init() {
- if [ -f "$SETTINGS_STORAGE" ]; then
- while read -r line; do
- if [[ $(in_port $line) == "" ]]; then
- continue
- fi
- if [[ $(dest_address $line) == "" ]]; then
- continue
- fi
- if [[ $(dest_port $line) == "" ]]; then
- continue
- fi
- RULES+=("$line")
- done < $SETTINGS_STORAGE
- for rule in "${RULES[@]}"
- do
- if [[ $(iptables -t nat -L -n | grep "dpt:$(in_port $rule) to:$(dest_address $rule):$(dest_port $rule)") == "" ]]; then
- echo $(in_port $rule) $(dest_address $rule) $(dest_port $rule) > /dev/null
- fi
- done
- fi
- check_interface
- }
- install() {
- if [[ $(crontab -l | grep "@reboot /usr/sbin/port-forward.sh init") != "" ]]; then
- if [[ $2 != "forced" ]]; then
- echo "Seems like already installed!"
- echo "To force the installation run this script as 'install forced'"
- exit 1
- fi
- fi
- systemctl enable cron
- cp $1 /usr/sbin/port-forward.sh
- if [[ $? != 0 ]]; then
- echo "Copy script to /usr/sbin/port-forward.sh failed"
- exit 1
- fi
- echo -e "@reboot /usr/sbin/port-forward.sh init" > /tmp/cronrule.tmp
- crontab /tmp/cronrule.tmp
- rm /tmp/cronrule.tmp
- enable_forwarding
- rm $1
- clear
- echo "Installed"
- echo "Using via 'port-forward.sh'"
- echo "Edit via 'nano /usr/sbin/port-forward.sh'"
- }
- if [[ $1 == "init" ]]; then
- check_to_root
- init
- exit 0
- fi
- if [[ $1 == "install" ]]; then
- check_to_root
- install $0 $2
- exit 0
- fi
- if [[ $1 == "add" ]]; then
- if [[ $2 == "" ]]; then
- echo "Expected inport after 'add' command"
- exit 1
- fi
- if [[ $3 == "" ]]; then
- echo "Expected destination address after 'add <inport>' command"
- exit 1
- fi
- if [[ $4 == "" ]]; then
- echo "Expected destination port after 'add <inport> <address>' command"
- exit 1
- fi
- check_to_root
- init
- add $2 $3 $4
- exit 0
- fi
- if [[ $1 == "del" ]]; then
- if [[ $2 == "" ]]; then
- echo "Expected inport after 'del' command"
- exit 1
- fi
- if [[ $3 == "" ]]; then
- echo "Expected destination address after 'del <inport>' command"
- exit 1
- fi
- if [[ $4 == "" ]]; then
- echo "Expected destination port after 'del <inport> <address>' command"
- exit 1
- fi
- check_to_root
- init
- del $2 $3 $4
- exit 0
- fi
- if [[ $1 == "list" ]]; then
- check_to_root
- init
- echo "Input interface: $INPUT_INTERFACE"
- echo "Output interface: $OUTPUT_INTERFACE"
- echo ""
- for rule in "${RULES[@]}"
- do
- echo -e "[$(in_port $rule)] -> $(dest_address $rule):$(dest_port $rule)"
- echo -e "Remove command: del $(in_port $rule) $(dest_address $rule) $(dest_port $rule)"
- echo ""
- done
- exit 0
- fi
- usage
|