UFW: Chỉ cho phép lưu lượng truy cập từ một miền có địa chỉ IP động


32

Tôi chạy một VPS mà tôi muốn bảo mật bằng UFW, chỉ cho phép kết nối với cổng 80. Tuy nhiên, để có thể quản trị nó từ xa, tôi cần mở cổng 22 và có thể truy cập tại nhà.

Tôi biết rằng UFW có thể được cấu hình để chỉ cho phép kết nối với một cổng từ địa chỉ IP cụ thể:

ufw allow proto tcp from 123.123.123.123 to any port 22

Nhưng địa chỉ IP của tôi là động, vì vậy đây chưa phải là giải pháp.

Câu hỏi là: Tôi có độ phân giải DNS động với DynDNS, vậy có thể tạo Quy tắc bằng tên miền thay vì IP không?

Tôi đã thử điều này:

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

nhưng tôi đã nhận ERROR: Bad source address

Câu trả lời:


47

Tôi không tin điều này là có thể với ufw. ufwchỉ là một lối vào iptablesmà cũng thiếu tính năng này, vì vậy một cách tiếp cận sẽ là tạo một mục crontab sẽ chạy định kỳ và kiểm tra xem địa chỉ IP có thay đổi hay không. Nếu nó có thì nó sẽ cập nhật nó.

Bạn có thể bị cám dỗ để làm điều này:

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

Nhưng điều này sẽ phân giải tên máy chủ thành IP và sử dụng quy tắc đó cho quy tắc, vì vậy nếu sau này IP thay đổi quy tắc này sẽ trở thành không hợp lệ.

Ý tưởng thay thế

Bạn có thể tạo một tập lệnh như vậy, được gọi là 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

nguồn: Sử dụng IPTables với tên máy chủ IP động như dyndns.org

Với tập lệnh này được lưu, bạn có thể tạo một mục crontab như vậy trong tệp /etc/crontab:

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

Mục nhập này sau đó sẽ chạy tập lệnh cứ sau 5 phút, kiểm tra xem địa chỉ IP được gán cho tên máy chủ đã thay đổi chưa. Nếu vậy thì nó sẽ tạo ra một quy tắc mới cho phép nó, đồng thời xóa quy tắc cũ cho địa chỉ IP cũ.


2
Thật ngớ ngẩn khi tôi không nghĩ đến việc giải quyết tên máy chủ theo định kỳ. Tôi đã sửa đổi tập lệnh của bạn (thêm ghi nhật ký, v.v.) và nó hoạt động như một nét duyên dáng. Cảm ơn bạn!
Carles Sala

@CarlesSala - rất vui vì nó đã giải quyết vấn đề của bạn. Ngoài việc chấp nhận, bạn cũng có thể nâng cấp 8-).
slm

1
lưu ý: trên Debian 7 tôi đã phải đổi dòng Current_IP=$(host $HOSTNAME | cut -f4 -d' ')thànhCurrent_IP=$(host $HOSTNAME | head -n1 | cut -f4 -d ' ')
Kstallian

Tôi có thể thấy điều này khi sử dụng trạng thái ufw verbose không? Ý tôi là, các quy tắc?
Freedo

@Freedo không chắc chắn, hãy thử nó và xem những gì sẽ xảy ra.
slm

8

Tôi biết điều này đã cũ nhưng tôi đã chạy qua nó và kết thúc với giải pháp này cuối cùng có vẻ tốt hơn vì không cần tệp nhật ký và rất dễ dàng để thêm các máy chủ bổ sung khi cần. Hoạt động như một lá bùa!

Nguồn: http://rdstash.blogspot.ch/2013/09/allow-host-with-dynamic-ip- phiên.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

xin lỗi tôi là một người mới Tôi cần lưu trữ tập lệnh này ở đâu và nơi tôi thay đổi mọi thứ để phản ánh trường hợp cụ thể của mình?
Freedo

5

Dựa trên các câu trả lời trước, tôi đã cập nhật đoạn dưới đây dưới dạng tập lệnh bash hoạt động trên 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

Điều đó thậm chí có thể được thêm vào để cronnó tự chạy theo định kỳ.
Tim Kennedy

Đó là những gì tôi đã làm;)
Mattias Pettersson

Tập lệnh này có một vấn đề nhỏ: trong lần sử dụng đầu tiên nếu bạn quên chạy bằng root, nó sẽ tạo tệp nhật ký nhưng không thêm quy tắc. Sau đó, nếu bạn chạy lại với quyền root, nó sẽ chỉ nói 'địa chỉ ip không thay đổi'. Nó phải được chạy như root lần đầu tiên! Ngoài ra, sẽ là tốt để thay đổi LOGFILE=$HOME/ufw.logđể LOGFILE=$HOME/ufw.$HOSTNAME.logcho phép nhiều hơn một tập lệnh chạy cùng một lúc
Guerlando OCs

@GuerlandoOCs làm thế nào để bạn thiết lập lại nếu bạn gặp phải vấn đề này?
Matthew

0

Dựa trên tất cả các câu trả lời trước khi tôi kết hợp chúng. Không cần logfile. Đã thử nghiệm trên 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

Bạn có thể thêm một cổng vào quy tắc với tham số "port". ví dụ:

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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.