UFW: อนุญาตการรับส่งข้อมูลจากโดเมนที่มีที่อยู่ IP แบบไดนามิกเท่านั้น


32

ฉันใช้งาน VPS ซึ่งฉันต้องการความปลอดภัยโดยใช้ UFW อนุญาตให้เชื่อมต่อกับพอร์ต 80 เท่านั้นอย่างไรก็ตามเพื่อให้สามารถจัดการได้จากระยะไกลฉันต้องเปิดพอร์ต 22 และทำให้สามารถเข้าถึงได้จากที่บ้าน

ฉันรู้ว่า UFW สามารถกำหนดค่าให้อนุญาตการเชื่อมต่อพอร์ตจากที่อยู่ IP ที่ระบุเท่านั้น:

ufw allow proto tcp from 123.123.123.123 to any port 22

แต่ที่อยู่ IP ของฉันเป็นแบบไดนามิกดังนั้นนี่ยังไม่ใช่วิธีแก้ปัญหา

คำถามคือ: ฉันมีการแก้ไข DNS แบบไดนามิกกับ DynDNS ดังนั้นจึงเป็นไปได้ที่จะสร้างกฎโดยใช้โดเมนแทน IP หรือไม่

ฉันได้ลองแล้ว:

ufw allow proto tcp from mydomain.dyndns.org to any port 22

แต่ฉันได้ ERROR: Bad source address

คำตอบ:


47

ufwผมไม่เชื่อว่าเรื่องนี้เป็นไปได้ด้วย ufwเป็นเพียงส่วนหน้าiptablesซึ่งขาดคุณสมบัตินี้ดังนั้นวิธีการหนึ่งก็คือการสร้างรายการ crontab ซึ่งจะรันเป็นระยะและตรวจสอบว่าที่อยู่ IP มีการเปลี่ยนแปลงหรือไม่ หากมีแล้วมันจะอัปเดต

คุณอาจถูกล่อลวงให้ทำเช่นนี้:

$ iptables -A INPUT -p tcp --src mydomain.dyndns.org --dport 22 -j ACCEPT

แต่สิ่งนี้จะแก้ไขชื่อโฮสต์เป็น IP และใช้สำหรับกฎนั้นดังนั้นหาก IP ในภายหลังการเปลี่ยนแปลงกฎนี้จะไม่ถูกต้อง

แนวคิดทางเลือก

คุณสามารถสร้างสคริปต์อย่างที่เรียกว่า, iptables_update.bash.

#!/bin/bash
#allow a dyndns name

HOSTNAME=HOST_NAME_HERE
LOGFILE=LOGFILE_NAME_HERE

Current_IP=$(host $HOSTNAME | cut -f4 -d' ')

if [ $LOGFILE = "" ] ; then
  iptables -I INPUT -i eth1 -s $Current_IP -j ACCEPT
  echo $Current_IP > $LOGFILE
else

  Old_IP=$(cat $LOGFILE)

  if [ "$Current_IP" = "$Old_IP" ] ; then
    echo IP address has not changed
  else
    iptables -D INPUT -i eth1 -s $Old_IP -j ACCEPT
    iptables -I INPUT -i eth1 -s $Current_IP -j ACCEPT
    /etc/init.d/iptables save
    echo $Current_IP > $LOGFILE
    echo iptables have been updated
  fi
fi

แหล่งที่มา: การใช้ IPTables กับชื่อโฮสต์ IP แบบไดนามิกเช่น dyndns.org

เมื่อบันทึกสคริปต์นี้แล้วคุณสามารถสร้างรายการ crontab ในไฟล์ได้/etc/crontabดังนี้

*/5 * * * * root /etc/iptables_update.bash > /dev/null 2>&1

รายการนี้จะเรียกใช้สคริปต์ทุก 5 นาทีตรวจสอบเพื่อดูว่าที่อยู่ IP ที่กำหนดให้กับชื่อโฮสต์มีการเปลี่ยนแปลง ถ้าเป็นเช่นนั้นมันจะสร้างกฎใหม่ที่อนุญาตในขณะที่การลบกฎเก่าสำหรับที่อยู่ IP เก่า


2
ช่างโง่เหลือเกินที่ฉันไม่ได้คิดถึงการแก้ไขชื่อโฮสต์เป็นระยะ ฉันแก้ไขสคริปต์ของคุณ (เพิ่มการบันทึกเป็นต้น) และทำงานได้อย่างมีเสน่ห์ ขอขอบคุณ!
Carles Sala

@CarlesSala - ดีใจที่ได้แก้ไขปัญหาของคุณ นอกจากการยอมรับคุณยังสามารถโหวตได้ 8-)
slm

1
หมายเหตุ: ใน Debian 7 ฉันต้องเปลี่ยนบรรทัดCurrent_IP=$(host $HOSTNAME | cut -f4 -d' ')เป็นCurrent_IP=$(host $HOSTNAME | head -n1 | cut -f4 -d ' ')
Krystian

ฉันจะสามารถเห็นสิ่งนี้เมื่อใช้สถานะ verfose ufw หรือไม่ ฉันหมายถึงกฎเหรอ?
Freedo

@ เฟรโด้ไม่แน่ใจลองและดูว่าเกิดอะไรขึ้น
slm

8

ฉันรู้ว่ามันเก่า แต่ฉันวิ่งข้ามมันและจบลงด้วยโซลูชันนี้ในท้ายที่สุดซึ่งดูเหมือนจะดียิ่งขึ้นเพราะไม่จำเป็นต้องมีไฟล์บันทึกและมันง่ายมากที่จะเพิ่มโฮสต์เพิ่มเติมตามต้องการ ทำงานเหมือนจับใจ!

ที่มา: http://rdstash.blogspot.ch/2013/09/allow-host-with-dynamic-ip-through.html

#!/bin/bash

DYNHOST=$1
DYNHOST=${DYNHOST:0:28}
DYNIP=$(host $DYNHOST | grep -iE "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+" |cut -f4 -d' '|head -n 1)

# Exit if invalid IP address is returned
case $DYNIP in
0.0.0.0 )
exit 1 ;;
255.255.255.255 )
exit 1 ;;
esac

# Exit if IP address not in proper format
if ! [[ $DYNIP =~ (([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]) ]]; then
exit 1
fi

# If chain for remote doesn't exist, create it
if ! /sbin/iptables -L $DYNHOST -n >/dev/null 2>&1 ; then
/sbin/iptables -N $DYNHOST >/dev/null 2>&1
fi

# Check IP address to see if the chain matches first; skip rest of script if update is not needed
if ! /sbin/iptables -n -L $DYNHOST | grep -iE " $DYNIP " >/dev/null 2>&1 ; then


# Flush old rules, and add new
/sbin/iptables -F $DYNHOST >/dev/null 2>&1
/sbin/iptables -I $DYNHOST -s $DYNIP -j ACCEPT

# Add chain to INPUT filter if it doesn't exist
if ! /sbin/iptables -C INPUT -t filter -j $DYNHOST >/dev/null 2>&1 ; then
/sbin/iptables -t filter -I INPUT -j $DYNHOST
fi

fi

ขอโทษฉันมือใหม่เล็กน้อย ฉันต้องเก็บสคริปต์นี้ไว้ที่ไหนและฉันจะเปลี่ยนสิ่งต่าง ๆ อย่างไรเพื่อให้สอดคล้องกับกรณีของฉัน
Freedo

5

จากคำตอบก่อนหน้าฉันได้อัปเดตข้อมูลต่อไปนี้เป็นสคริปต์ทุบตีที่ทำงานกับ Debian Jessie

#!/bin/bash
HOSTNAME=dynamichost.domain.com
LOGFILE=$HOME/ufw.log
Current_IP=$(host $HOSTNAME | head -n1 | cut -f4 -d ' ')

if [ ! -f $LOGFILE ]; then
    /usr/sbin/ufw allow from $Current_IP to any port 22 proto tcp
    echo $Current_IP > $LOGFILE
else

    Old_IP=$(cat $LOGFILE)
    if [ "$Current_IP" = "$Old_IP" ] ; then
        echo IP address has not changed
    else
        /usr/sbin/ufw delete allow from $Old_IP to any port 22 proto tcp
        /usr/sbin/ufw allow from $Current_IP to any port 22 proto tcp
        echo $Current_IP > $LOGFILE
        echo iptables have been updated
    fi
fi

ที่อาจถูกเพิ่มเข้าไปเพื่อcronให้มันทำงานเป็นระยะด้วยตัวเอง
Tim Kennedy

นั่นคือสิ่งที่ฉันทำ;)
Mattias Pettersson

สคริปต์นี้มีปัญหาเล็กน้อย: ในการใช้ครั้งแรกหากคุณลืมที่จะเรียกใช้ในฐานะ root มันจะสร้างไฟล์บันทึก แต่ไม่ได้เพิ่มกฎ จากนั้นถ้าคุณทำงานอีกครั้งในขณะที่รูทเครื่องก็จะบอกว่า 'ที่อยู่ IP ไม่เปลี่ยน' มันจะต้องถูกเรียกใช้ในฐานะ root ในครั้งแรก! นอกจากนี้ควรเปลี่ยนLOGFILE=$HOME/ufw.logเป็นLOGFILE=$HOME/ufw.$HOSTNAME.logอนุญาตให้ใช้สคริปต์มากกว่าหนึ่งสคริปต์ในเวลาเดียวกัน
Guerlando OCs

@GuerlandoOCs คุณจะรีเซ็ตอย่างไรหากพบปัญหานี้
แมทธิว

0

ตามคำตอบทั้งหมดก่อนที่จะรวมเข้าด้วยกัน ไม่จำเป็นต้องใช้ไฟล์บันทึก ทดสอบบน Ubuntu 18.04

#!/bin/bash
HOSTNAME=YOUR.DNS.NAME.HERE

if [[ $EUID -ne 0 ]]; then
   echo "This script must be run as root"
   exit 1
fi

new_ip=$(host $HOSTNAME | head -n1 | cut -f4 -d ' ')
old_ip=$(/usr/sbin/ufw status | grep $HOSTNAME | head -n1 | tr -s ' ' | cut -f3 -d ' ')

if [ "$new_ip" = "$old_ip" ] ; then
    echo IP address has not changed
else
    if [ -n "$old_ip" ] ; then
        /usr/sbin/ufw delete allow from $old_ip to any
    fi
    /usr/sbin/ufw allow from $new_ip to any comment $HOSTNAME
    echo iptables have been updated
fi

คุณสามารถเพิ่มพอร์ตเข้ากับกฎด้วยพารามิเตอร์ "พอร์ต" เช่น:

if [ -n "$old_ip" ] ; then
    /usr/sbin/ufw delete allow from $old_ip to any port 22
fi
/usr/sbin/ufw allow from $new_ip to any port 22 comment $HOSTNAME
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.