SSHの接続元IP制限(国単位)をhosts.allow, hosts.denyで
まとめ
- iptablesにIPアドレスを大量に登録するのは、いろいろ大変なので、動的に制御できたら嬉しい
- Debian/Ubuntuだと、
/etc/hosts.allow
、/etc/hosts.deny
でaclexec
というオプション1を使用してプログラムの終了コードでアクセス制御ができる - GeoIPデータベースを利用してIPアドレスの国判定(IPv4/v6対応)のスクリプト書いた
- OpenSSH自体では、6.7でtcpwrappers/libwrapが除かれた2が、Debian/Ubuntu版openssh-serverではtcpwrappers/libwrapのサポートが継続中3という実は微妙な状況
書いたスクリプト
#!/usr/bin/env python3 # # install required packeges: # sudo apt-get install python3-geoip geoip-database libgeoip1 # # download script: # sudo curl -sS -o /usr/local/bin/check_geoip.py https://gist.githubusercontent.com/kacchan822/f9240646cfd78a5290a2ec95d844b1a0/raw/a5d7047beb493dfdfc63c70b00b3b3c5595e1d64/check_geoip.py # sudo chmod +x /usr/local/bin/check_geoip.py # # setting up hosts.allow and hosts.deny: # sudo sh -c 'echo "sshd: ALL: aclexec /usr/local/bin/check_geoip.py %a" >> /etc/hosts.allow' # sudo sh -c 'echo "sshd: ALL" >> /etc/hosts.deny' # import ipaddress import sys import GeoIP # CHANGE if allow from other countory. ALLOWED_COUNTORY = ['JP',] # Check Value try: ip = ipaddress.ip_address(sys.argv[1]) except ValueError: sys.exit(1) # Local IP is permitted if ip.is_private: sys.exit(0) # Check IP address version if ip.version == 4: gi = GeoIP.new(GeoIP.GEOIP_STANDARD) cc = gi.country_code_by_addr(str(ip)) else: gi = GeoIP.open('/usr/share/GeoIP/GeoIPv6.dat', GeoIP.GEOIP_STANDARD) cc = gi.country_code_by_addr_v6(str(ip)) # Chaeck Countory Code if cc in ALLOWED_COUNTORY: sys.exit(0) else: sys.exit(1)
https://gist.github.com/kacchan822/f9240646cfd78a5290a2ec95d844b1a0
ポイント
- ALLOWED_COUNTORY
に許可したい国コード(2文字)を入れれば、日本以外も許可できる
- IPv4,IPv6の両方に対応
- ローカルIPは許可
つかいかた
上記スクリプトの上部にもあるけど...
# install required packeges ubuntu@ubuntu1604:~$ sudo apt-get install python3-geoip geoip-database libgeoip1 # download script ubuntu@ubuntu1604:~$ sudo curl -sS -o /usr/local/bin/check_geoip.py https://gist.githubusercontent.com/kacchan822/f9240646cfd78a5290a2ec95d844b1a0/raw/a5d7047beb493dfdfc63c70b00b3b3c5595e1d64/check_geoip.py ubuntu@ubuntu1604:~$ sudo chmod +x /usr/local/bin/check_geoip.py # setting up hosts.allow and hosts.deny ubuntu@ubuntu1604:~$ sudo sh -c 'echo "sshd: ALL: aclexec /usr/local/bin/check_geoip.py %a" >> /etc/hosts.allow' ubuntu@ubuntu1604:~$ sudo sh -c 'echo "sshd: ALL" >> /etc/hosts.deny'
おわりに
openssh-serverのTCPwrapper対応がいつからなくなるのかには気をつけないと...。
-
http://manpages.ubuntu.com/manpages/artful/man5/hosts_options.5.html↩
-
apt-get changelog openssh-server
で確認できるchangelogに次の記載がある(Ubuntu 17.10で確認)。”openssh (1:6.7p1-1) unstable; urgency=medium … * Restore TCP wrappers support, removed upstream in 6.7. It is true that dropping this reduces preauth attack surface in sshd. On the other hand, this support seems to be quite widely used, and abruptly dropping it (from the perspective of users who don’t read openssh-unix-dev) could easily cause more serious problems in practice. It’s not entirely clear what the right long-term answer for Debian is, but it at least probably doesn’t involve dropping this feature shortly before a freeze. …”↩