"시놀로지 도커 설정"의 두 판 사이의 차이

DM wiki
둘러보기로 이동 검색으로 이동
(새 문서: ===== Nginx 프록시 서버 ===== * 이건 도커가 아닌 시놀로지 VMM에 위치 * Alpine * Cloudflare 연동 expose 서버 * 일본 특성상 IPv4 포트가 매우 제한적...)
 
잔글
1번째 줄: 1번째 줄:
===== Nginx 프록시 서버 =====
=== 외부 노출 서버 (IPv6 보고 및 웹 프록시) ===


* 이건 도커가 아닌 시놀로지 VMM에 위치
* 이건 도커가 아닌 시놀로지 VMM에 위치
* Alpine
* alpine
* Cloudflare 연동 expose 서버
 
==== 마운트 설정 ====
 
* alpine에 nfsmount 설치
** apk add nfsmount
* /etc/fstab에 다음 내용 추가
** 맨 뒤의 _netdev와 0 0을 꼭 추가해야 한다<syntaxhighlight lang="sh">
내부서버IP:/volume1/시놀로지폴더 /마운트경로 nfs nfsvers=3,rsize=524288,wsize=524288,ro,auto,nolock,_netdev 0 0
</syntaxhighlight>
 
==== Cloudflare 연동 IP 등록 ====
 
* 일본 특성상 IPv4 포트가 매우 제한적으로 열려 있고, 10000번대 밑으로는 아예 열리지도 않음
* 일본 특성상 IPv4 포트가 매우 제한적으로 열려 있고, 10000번대 밑으로는 아예 열리지도 않음
* IPv6는 이런 제한이 없음. 공유기가 각각의 머신에 뿌려주는 IP는 DHCP라기보다는 일본 인터넷에 직접 연결된 공인 IP.
* IPv6는 이런 제한이 없음. 공유기가 각각의 머신에 뿌려주는 IP는 DHCP라기보다는 일본 인터넷에 직접 연결된 공인 IP.
** IPv6는 설계시부터 모든 기기가 고유의 공인 IP를 갖는 형태로 설계됨. 다만 그 특성상 보안에 취약하므로, 영구 IPv6 주소와 별개로 임시 IPv6가 부여되어, 수시로 주소가 바뀜.
** IPv6는 설계시부터 모든 기기가 고유의 공인 IP를 갖는 형태로 설계됨. 다만 그 특성상 보안에 취약하므로, 영구 IPv6 주소와 별개로 임시 IPv6가 부여되어, 수시로 주소가 바뀜.
** 주소 바뀜을 체크하여, Cloudflare DNS에 등록해 주는 역할
** 주소 바뀜을 체크하여, Cloudflare DNS에 등록해 주는 역할 (v6 레코드인 AAAA를 업데이트 함)
** 다음 파일을 alpine 서버의 /etc/init.d에 등록
** 다음 파일을 alpine 서버의 /etc/init.d에 저장. (파일 이름 cloudflare-alpine.service)<syntaxhighlight lang="shell" line="1">
** <syntaxhighlight lang="shell" line="1">
#!/sbin/openrc-run
#!/sbin/openrc-run


22번째 줄: 32번째 줄:
description="Update Cloudflare DNS"
description="Update Cloudflare DNS"


command="/usr/bin/python3 /mnt/yukina/alpine-config/cloudflare/cloudflare-alpine.py"
command="/usr/bin/python3 /root/cloudflare-alpine.py"
# command="/usr/bin/python3 /root/cloudflare-alpine.py"
pidfile="/var/run/cloudflare/cloudflare.pid"
pidfile="/var/run/cloudflare/cloudflare.pid"
command_background="yes"
command_background="yes"
38번째 줄: 47번째 줄:
         mkdir -p /var/run/cloudflare || return 1
         mkdir -p /var/run/cloudflare || return 1
}
}
</syntaxhighlight>실제 업데이트를 수행하는 Python 파일을 위의 서비스 스크립트에 지정된 위치로 잘 저장<syntaxhighlight lang="python3" line="1">
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
import requests
import json
from time import sleep
CLOUDFLARE_KEY = 'XXX'
CLOUDFLARE_ZONE_ID = 'XXX'
CLOUDFLARE_DNS_TOKEN = 'XXX'
CLOUDFLARE_HEADER = {
    'Authorization': 'Bearer {}'.format(CLOUDFLARE_DNS_TOKEN),
    'Content-Type': 'application/json'
}
DNS_GET_URL = 'https://api.cloudflare.com/client/v4/zones/{}/dns_records'.format(CLOUDFLARE_ZONE_ID)
device = 'eth0'
addr_file = '/tmp/cloudflare.addr6'
def check():
    addr = ''
    try:
        with open(addr_file, 'r') as f:
            addr = f.read()
    except:
        pass
    get_addr_cmd = "ip -6 addr list scope global $device | " \
                  "grep -v ' fd' | " \
                  "grep -v 'deprecated' | " \
                  "grep -v 'mngtmpaddr' | " \
                  "head -n 2 | " \
                  "tail -n 1"
    new_addr = os.popen(get_addr_cmd).read()
    new_addr = new_addr.split()[1]
    new_addr = new_addr.split('/')[0]
    if addr == new_addr:
        print('same ip {}'.format(new_addr))
    else:
        r = requests.get(DNS_GET_URL, headers=CLOUDFLARE_HEADER)
        j = json.loads(r.text)
        for item in j['result']:
            dns_put_url = DNS_GET_URL + '/' + item['id']
            new_data = dict(
                type=item['type'],
                name=item['name'],
                content=new_addr,
            )
            if item['type'] == 'AAAA':
                new_data['proxied'] = True
                requests.put(dns_put_url, data=json.dumps(new_data), headers=CLOUDFLARE_HEADER)
            elif item['type'] == 'TXT':
                new_data['content'] = 'v=spf1 {} ~all'.format(new_addr)
                requests.put(dns_put_url, data=json.dumps(new_data), headers=CLOUDFLARE_HEADER)
        with open(addr_file, 'w') as f:
            f.write(new_addr)
            f.close()
        print('updated ip {}'.format(new_addr))
       
while True:
    check()
    sleep(60)
</syntaxhighlight>
** 그 후 서비스 등록<syntaxhighlight lang="sh">
rc-update add cloudflare-alpine.service
rc-service cloudflare-alpine.service restart
rc-update -u
</syntaxhighlight>
</syntaxhighlight>


==== Nginx 웹 프록시 ====
* Cloudflare로부터 오는 HTTPS 요청을 처리하여, 내부 서버에 전달
* 처음 도입 목적은 Cloudflare의 IPv6 over IPv4 기능을 이용하기 위함
* 생각해보니 외부/내부를 분리하여 보안성도 높아지고, 도커를 이용한 로드밸런서 구현 및 포트 번호 추상화가 가능해져 채택
* /etc/nginx/conf.d는 시놀로지에 config를 등록해 놓고 폴더째로 마운트
* wiki-proxy.conf 예시
** proxy_set_header를 설정해야 내부 서버에서 보이는 접속 요청 IP가 실제 사용자의 IP로 제대로 뜬다
** 내부 서버사이의 통신은 http로 하여 속도 향상 (방화벽 설정은 따로)<syntaxhighlight lang="nginx">
server {
    listen  80;
    listen  [::]:80;
    server_name wiki.dong-min.kim;
       
    location / {
        return 301 https://$server_name$request_uri;
    }
}
server {
    listen 443 ssl;
listen [::]:443 ssl;
    ssl_certificate pem파일;
    ssl_certificate_key key파일;
       
server_name wiki.dong-min.kim;
    server_tokens off;
 
location / {
        proxy_set_header  Host $host;
        proxy_set_header  X-Real-IP $remote_addr;
        proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header  X-Forwarded-Host $server_name;
        proxy_set_header  Client-IP $remote_addr;
proxy_pass http://내부 서버 주소:포트;
}
}
</syntaxhighlight>
*
*
*
*
* nginx 1.17.8 alpine
* nginx 1.17.8 alpine
* php 7.2.9 fpm alpine  
* php 7.2.9 fpm alpine
* 위키
* 위키
** 위키
** 위키
47번째 줄: 175번째 줄:
** parsoid
** parsoid
** mathoid
** mathoid
**  
**
* 토렌트
* 토렌트
** archlinux deluge openvpn
** archlinux deluge openvpn

2020년 2월 27일 (목) 07:32 판

외부 노출 서버 (IPv6 보고 및 웹 프록시)

  • 이건 도커가 아닌 시놀로지 VMM에 위치
  • alpine

마운트 설정

  • alpine에 nfsmount 설치
    • apk add nfsmount
  • /etc/fstab에 다음 내용 추가
    • 맨 뒤의 _netdev와 0 0을 꼭 추가해야 한다
      내부서버IP:/volume1/시놀로지폴더 /마운트경로 nfs nfsvers=3,rsize=524288,wsize=524288,ro,auto,nolock,_netdev 0 0
      

Cloudflare 연동 IP 등록

  • 일본 특성상 IPv4 포트가 매우 제한적으로 열려 있고, 10000번대 밑으로는 아예 열리지도 않음
  • IPv6는 이런 제한이 없음. 공유기가 각각의 머신에 뿌려주는 IP는 DHCP라기보다는 일본 인터넷에 직접 연결된 공인 IP.
    • IPv6는 설계시부터 모든 기기가 고유의 공인 IP를 갖는 형태로 설계됨. 다만 그 특성상 보안에 취약하므로, 영구 IPv6 주소와 별개로 임시 IPv6가 부여되어, 수시로 주소가 바뀜.
    • 주소 바뀜을 체크하여, Cloudflare DNS에 등록해 주는 역할 (v6 레코드인 AAAA를 업데이트 함)
    • 다음 파일을 alpine 서버의 /etc/init.d에 저장. (파일 이름 cloudflare-alpine.service)
      #!/sbin/openrc-run
      
      # $apk add python3
      # $apk add py3-requests
      # Copy this file into /etc/init.d/
      # Test by $rc-service cloudflare-alpine.service start
      # $rc-update add cloudflare-alpine.service
      # $rc-service cloudflare-alpine.service restart
      # $rc-update -u
      
      description="Update Cloudflare DNS"
      
      command="/usr/bin/python3 /root/cloudflare-alpine.py"
      pidfile="/var/run/cloudflare/cloudflare.pid"
      command_background="yes"
      
      depend() {
              need net
              need nfsmount
              need sshd
              after iptables
      }
      
      start_pre() {
              ebegin "Starting cloudflare"
              mkdir -p /var/run/cloudflare || return 1
      }
      
      실제 업데이트를 수행하는 Python 파일을 위의 서비스 스크립트에 지정된 위치로 잘 저장
      #!/usr/bin/env python
      # -*- coding: utf-8 -*-
      
      import os
      import requests
      import json
      from time import sleep
      
      CLOUDFLARE_KEY = 'XXX'
      CLOUDFLARE_ZONE_ID = 'XXX'
      CLOUDFLARE_DNS_TOKEN = 'XXX'
      
      CLOUDFLARE_HEADER = {
          'Authorization': 'Bearer {}'.format(CLOUDFLARE_DNS_TOKEN),
          'Content-Type': 'application/json'
      }
      DNS_GET_URL = 'https://api.cloudflare.com/client/v4/zones/{}/dns_records'.format(CLOUDFLARE_ZONE_ID)
      
      device = 'eth0'
      addr_file = '/tmp/cloudflare.addr6'
      
      def check():
          addr = ''
          try:
              with open(addr_file, 'r') as f:
                  addr = f.read()
          except:
              pass
      
          get_addr_cmd = "ip -6 addr list scope global $device | " \
                         "grep -v ' fd' | " \
                         "grep -v 'deprecated' | " \
                         "grep -v 'mngtmpaddr' | " \
                         "head -n 2 | " \
                         "tail -n 1"
      
          new_addr = os.popen(get_addr_cmd).read()
          new_addr = new_addr.split()[1]
          new_addr = new_addr.split('/')[0]
      
      
          if addr == new_addr:
              print('same ip {}'.format(new_addr))
          else:
              r = requests.get(DNS_GET_URL, headers=CLOUDFLARE_HEADER)
              j = json.loads(r.text)
      
              for item in j['result']:
                  dns_put_url = DNS_GET_URL + '/' + item['id']
                  new_data = dict(
                      type=item['type'],
                      name=item['name'],
                      content=new_addr,
                  )
                  if item['type'] == 'AAAA':
                      new_data['proxied'] = True
                      requests.put(dns_put_url, data=json.dumps(new_data), headers=CLOUDFLARE_HEADER)
                  elif item['type'] == 'TXT':
                      new_data['content'] = 'v=spf1 {} ~all'.format(new_addr)
                      requests.put(dns_put_url, data=json.dumps(new_data), headers=CLOUDFLARE_HEADER)
      
              with open(addr_file, 'w') as f:
                  f.write(new_addr)
                  f.close()
              print('updated ip {}'.format(new_addr))
              
      
      while True:
          check()
          sleep(60)
      
    • 그 후 서비스 등록
      rc-update add cloudflare-alpine.service
      rc-service cloudflare-alpine.service restart
      rc-update -u
      

Nginx 웹 프록시

  • Cloudflare로부터 오는 HTTPS 요청을 처리하여, 내부 서버에 전달
  • 처음 도입 목적은 Cloudflare의 IPv6 over IPv4 기능을 이용하기 위함
  • 생각해보니 외부/내부를 분리하여 보안성도 높아지고, 도커를 이용한 로드밸런서 구현 및 포트 번호 추상화가 가능해져 채택
  • /etc/nginx/conf.d는 시놀로지에 config를 등록해 놓고 폴더째로 마운트
  • wiki-proxy.conf 예시
    • proxy_set_header를 설정해야 내부 서버에서 보이는 접속 요청 IP가 실제 사용자의 IP로 제대로 뜬다
    • 내부 서버사이의 통신은 http로 하여 속도 향상 (방화벽 설정은 따로)
      server {
          listen   80;
          listen   [::]:80;
          server_name wiki.dong-min.kim;
              
          location / {
              return 301 https://$server_name$request_uri;
          }
      }
      
      server {
          listen 443 ssl;
      	listen [::]:443 ssl;
      
          ssl_certificate pem파일;
          ssl_certificate_key key파일;
              
      	server_name wiki.dong-min.kim;
          server_tokens off;
         
      	location / {
              proxy_set_header  Host $host;
              proxy_set_header  X-Real-IP $remote_addr;
              proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
              proxy_set_header  X-Forwarded-Host $server_name;
              proxy_set_header  Client-IP $remote_addr;
      		proxy_pass http://내부 서버 주소:포트;
      	}
      }
      
  • nginx 1.17.8 alpine
  • php 7.2.9 fpm alpine
  • 위키
    • 위키
    • restbase
    • parsoid
    • mathoid
  • 토렌트
    • archlinux deluge openvpn
  • busybox
  • gitlab
    • gitlab postgresql
    • redis
  • DB
    • cassandra 3.5
    • mysql5.7.29
  • wordpress
  • kb_apart

권한 관련