블로그 이미지
안녕하세요~ iolate(a.k.a. isho) 의 블로그 입니다~! iolate

카테고리

분류 전체보기 (194)
끄적끄적 (6)
Review (15)
IoT (8)
Linux, Server, Web (49)
Mac, iOS (36)
Embedded (15)
개발개발 (51)
Network (3)
기타 (11)
비공개글 (0)
Total775,841
Today20
Yesterday134

NextCloud 는 기본적으로 시스템의 디렉토리를 사용하지만,

추가로 External Storage Support 기능을 사용해서 FTP, S3 등등 외부 저장소를 마운트하여 사용할 수 있다.


처음엔 이렇게 연결하려고 했는데, 뭔가 안되어서 찾다보니, S3자체를 NextCloud의 주 저장소로 사용하는 방법이 있어서 그냥 그걸 사용해보기로 했음.

참고로 지금 하려는 주 저장소가 아니라 외부저장소로써 S3를 사용할 경우

(1) 사용자마다 S3 연결을 직접하지 못하고 관리자가 해줘야함

(2) 저장공간 사용 제약을 할 수 없음

(3) NextCloud의 공유 기능을 사용할 수 없음

요런 3가지 단점이 있다고 한다.


참고로 Amazon S3 뿐만 아니라 S3와 비슷한 object storage 류들도 사용이 가능하다고 함.

또한 S3와 연결된다고 해서 S3에서 직접 파일 브라우징을 할 순 없다고 한다. 파일 자체는 있지만 메타데이터가 없어서...

기존 설치된 NextCloud를 옮길 수도 없다. 새로 설치해야 됨.


nextcloud/config/config.php 파일 설정에

  'objectstore' => array(
    'class' => '\\OC\\Files\\ObjectStore\\S3',
    'arguments' => array(
      'bucket' => '버킷이름',
      'autocreate' => true,
      'key'    => 'IAM Access Key',
      'secret' => 'IAM Secret',
      'use_ssl' => true,
      'region' => 'AWS 리전, 서울이면 ap-northeast-2'
    ),
  ),

요 부분을 추가해두고 설치를 진행하면 된다.


이미 진행된 인스턴스가 있을 경우 nextcloud/data 폴더와 DB 테이블들을 날려버리고, config.php에 installed: true 라인 지우고, 마지막으로 config 폴더에 CAN_INSTALL 파일을 생성하고 접속하면 다시 설정부터 진행할 수 있다.


S3를 주 저장소로 할 경우 php의 파일 업로드 제한에 영향을 받지 않는 것 같다. 아마 S3 API 로 바로 업로드 시키는 듯?


참고: Configuring Object Storage as Primary Storage - https://docs.nextcloud.com/server/15/admin_manual/configuration_files/primary_storage.html


+ File lock 비활성화

NextCloud 는 공유된 파일을 2명 이상의 사용자가 동시에 편집해서 꼬이는 문제를 방지하기 위해 File locking 기능을 사용한다.

DB, 혹은 설정된 mem cache 에 lock 정보를 가지고 있고, 30분마다 cron이 지워주는 방식으로 작동한다는데, S3를 사용할 경우 끄는걸 권장한다는 듯? ( https://autoize.com/s3-compatible-storage-for-nextcloud/ )


일단 당장 내가 lock 으로 인한 문제를 발견해서(생성되고 파일을 빠르게 지울경우 뭔가 이상하게 lock 이 걸려서 파일 삭제가 안됨..) 그냥 꺼버렸음.


config.php에

  'filelocking.enabled' => false,

를 추가해주면 된다.

Posted by iolate
TAG nextcloud, S3

댓글을 달아 주세요

Docker로 설치해봤는데, docker 이미지는 web installer 방식이라 초기 설치시간이 오래걸리길래 그냥 네이티브로 깔았다.

참고로 아래 설치법은 일부 선택 옵션들을 포함하니 참고.

Installation on Linux — Nextcloud 여기 잘 설명되어 있으니 그냥 여길 봐도 된다. 좀 귀찮게 해서 그렇지...


1. apache2 + php7.4 설치

Ubuntu 18.04의 기본 php 는 7.0이다. 7.3 이상을 권장하니 7.4를 깔아주자

nginx도 못쓰는건 아닌데,, 왠지 apache2 가 기본값인 것 같아서 그냥 apache2 로 진행하였다.

sudo apt -y install software-properties-common
sudo add-apt-repository ppa:ondrej/php

sudo apt install apache2 libapache2-mod-php7.4 php7.4 php7.4-bcmath php7.4-bz2 \
    php7.4-curl php7.4-gd php7.4-gmp php7.4-intl php7.4-json php7.4-mbstring \
    php7.4-mysql php7.4-xml php7.4-zip libxml2


NextCloud 에서 imagic 모듈도 설치를 추천한다.

sudo apt install php-imagick


2. NextCloud 설치

php 기반의 프로그램이다. 웹사이트에서 받아서 적절한 위치에 압축을 풀어만 주면 됨.

https://nextcloud.com/install/#instructions-server


3. apache2 설정

/etc/apache2/site-available/cloud.conf (당연히 이름과 각종 경로는 알아서 수정..)

<VirtualHost *:80>
        ServerName 사이트주소

        DocumentRoot /var/www/nextcloud/
        <Directory /var/www/nextcloud/>
                Require all granted
                AllowOverride All
                Options FollowSymLinks MultiViews
        </Directory>

        LogLevel emerg
</VirtualHost>

apache2 에 필요/선택 모듈을 활성화해준다.

a2enmod rewrite headers env dir mime


4. php 설정

php 기본 설정은 업로드 용량이 2MB이므로, 조금 늘려준다.

메모리 제한값도 기본은 128MB이지만 추천은 512MB

sudo vi /etc/php/7.4/apache2/php.ini
memory_limit = 512M
post_max_size = 10G
upload_max_filesize = 10G


5. HTTPS 설정

이건 알아서 해주자.

Posted by iolate
TAG nextcloud

댓글을 달아 주세요

0. 용어 정리

PKI (Public Key Infrastructure); 공개키 기반 구조

X.509: 공개키 인증서와 인증 알고리즘을 사용하기 위한 PKI 표준

PKCS (Public Key Cryptography Standards): Private Key를 저장하는 문법에 관한 표준
            PKCS#1, PKCS#8, PKCS#12 등을 사용

CRL (Certificate Revocation List), OCSP (Online Certificate Status Protocol): 인증서 유효성 점검을 위한 표준/방법

CA (Certificate Authority): 인증 기관

ASN.1 (Abstract Syntax Notation One): 추상 구문 기법, 네트웍상의 데이터 교환을 정의한 프로토콜

RSA (Rivest–Shamir–Adleman): 공개키 암호시스템의 하나

ECDSA (Elliptic Curve Digital Signature Algorithm): 타원곡선을 이용한 전자서명 알고리즘


0-2. 인코딩/파일 종류 정리

참고로 당연히 아래에 적는 확장자는 참고용으로 강제사항은 아님.
PEM 포맷의 개인키를 my.key.pem, my.key, key.pem 등등 저장하기 나름.

인코딩에 따른 구분

 종류

 확장자

 설명

 DER (Distinguished Encoding Representation)

 .der

 ASN.1을 표현하는 방식의 종류. (바이너리로 저장됨)

 PEM (Privacy Enhanced Mail)

 .pem

 Base64로 인코딩된 ASCII 텍스트
 (표준으로 더 자주 사용됨)


내용에 따른 구분

 종류

 확장자

 설명

 Private Key

 .key

 개인키

 Certificate

 .cer (Windows 주로 사용)
 .crt (*NIX 주로 사용)

 인증서

 PKCS #12

 .p12, .pfx

 하나의 파일에 개인키, 인증서 등을 같이 저장하는 방식에 대한 표준

 Certificate Signing Request

 .csr

 인증서 발급을 위해 내 개인키 서명을 CA에게 보내기 위한 파일

 Serial .srl

 CA가 인증서를 발급할 때 Serial 을 관리하기 위한 파일



1. OpenSSL 명령어

* 기본 config 경로: /etc/pki/tls/openssl.cnf

1) Private Key 생성

openssl genrsa -out key.pem 2048


[옵션]

-des, -seed, -aes256, ...: 해당하는 방식으로 키 암호화. 미사용시 암호화 X

-passout pass:PASSWORD: 키를 암호화할 경우 암호 지정. 미사용시 입력 프롬프트가 뜸

-f4 (0x10001), -3: E value 지정. 기본값: -f4

1024, 2048, 3072, 4096, ...: Private Key Bit 크기. 아래 부록 참고




2) CSR 생성

openssl req -new -key key.pem -out my.csr


[옵션]

-md5, -sha1, -sha256, ...: 서명에 사용할 Digest. 기본값은 버전마다 다르고 적당히 sha256 사용.
            전체 목록은 openssl dgst -h

-subj: 인증서 주제 설정. 미사용시 입력 프롬프트 표시
    예시) -subj "/C=KR/O=sho/CN=SHO Certificate"

 필드

 의미

 예시

 /C=

 국가

 KR

 /ST=

 State, 한국이라면 시/도

 Seoul

 /L=

 Location

 Yongsan

 /O=

 Organization, 회사명

 회사

 /OU=

 Organization Unit, 부서명

 부서

 /CN=

 Common Name

 SHO Root CA, blog.ioate.kr 등




3) CSR로부터 인증서 생성

X.509 V3 확장 설정

(아래에서 사용할 ca.ext, end.ext 파일)

Web TLS 인증서 (CA용) - ca.ext

basicConstraints = critical, CA:TRUE
#basicConstraints = critical, CA:TRUE, pathlen:0

subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid:always,issuer
keyUsage = cRLSign, keyCertSign


Web TLS 인증서 (End-entity, 사이트용) - end.ext

basicConstraints = critical, CA:FALSE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
keyUsage = digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth, clientAuth
subjectAltName = DNS:blog.iolate.kr, IP:1.1.1.1


CA 인증서 생성

openssl x509 -req -days 3650 -extfile ca.ext -signkey key.pem -in my.csr -out root.crt


[옵션]

-set_serial 1: 시리얼 값 지정. 미지정시 임의값 생성

-md5, -sha1, -sha256, ...: 서명에 사용할 Digest.
            전체 목록은 openssl dgst -h
            직접 신뢰 설정을 하는 Root CA 가 아니라면, sha256 사용. sha1 등 취약한 digest 사용시 브라우저에서 경고함


End-entity 인증서 생성

openssl x509 -req -days 365 -extfile end.ext -CA root.crt -CAcreateserial -CAkey my.key -in my.csr -out end.crt
openssl x509 -req -days 365 -extfile end.ext -CA root.crt -CAserial root.srl -CAkey my.key -in my.csr -out end.crt


[옵션]

-CAcreateserial: 시리얼 자동 지정 및 시리얼 파일 생성 (.srl)

-CAserial root.srl: CAcreateserial 로 한번 발급한 이후에는 이 옵션으로 시리얼 생성 파일 입력

-md5, -sha1, -sha256, ...: 서명에 사용할 Digest. sha256 사용. sha1 등 취약한 digest 사용시 브라우저에서 경고함



4) 생성된 파일 정보 확인

CSR / 인증서 / 개인키

openssl [req/x509/rsa] -noout -text -in [my.csr/end.crt/my.key]
openssl [req/x509/rsa] -noout -modulus -in [my.csr/end.crt/my.key] | openssl md5



2. 부록

Private Key 비트 크기

출처: https://en.wikipedia.org/wiki/Key_size

(대략적 요약)

* 128bit AES가 충분한 보안 수준으로 고려되었지만, 양자 컴퓨터의 등장 후 비밀 문서에 256bit 사용 권고

* 1024bit RSA와 80bit 대칭키 /
   2048bit RSA와 112bit 대칭키 / 
   3072bit RSA와 128bit 대칭키 /
   15360bit RSA와 256bit 대칭키  가 서로 보안 수준이 비슷하다고 판단됨.

* 1024bit RSA는 2006~2010년에 취약해짐.
   2048bit RSA는 2030년까지 유효할 것으로 판단.
   2030년 이후에는 3072bit 사용 권고


3. 참고

Wikipedia, OpenSSL 문서, 등등...

(그때그때 정리해둔 문서를 다시 정리한거라 참고 URL이 없음..ㅠ)

Posted by iolate

댓글을 달아 주세요

cloud9 을 사용하거나,, 뭐 여튼 필요할떄만 쓰는 aws 인스턴스의 경우엔 ip 주소를 매번 확인해줘야하는 번거로움이 추가된다.
따라서 부팅시에 Route 53 A레코드를 변경해주는 스크립트를 작성해보았음.

IAM 권한도 적절히 필요하겠지만, 난 cloud9 instance를 사용해서인지, aws가 알아서 credential 을 관리해줘서 생략.
필요하다면 아래 참고 글 링크를 확인해보자.

아래 파이썬 스크립트를 적절한 곳에 만들어 주고, 상단 변수 역시 설정해준다. 난 ~/route53/update.py 라고 만들었음.
특정 인스턴스의 public ip 를 구해온 다음, 지정한 url의 A레코드 값을 변경(없으면 생성)해주는 코드이다.
호스팅 영역 ID는 Route 53 에서 해당 도메인 이름(ex.com)을 선택하면 볼 수 있고, URL 은 호스팅 영역 내에서 생성하는 서브도메인을 포함한 이름(abc.ex.com)의 형태를 입력해주자.

INSTANCE_REGION="ap-southeast-1"
INSTANCE_ID="i-~~~~~~~~~~"
DOMAIN_ZONE="호스팅 영역 ID (ZGWP~~~~~~)"
URL="사용할 도메인 (abc.ex.com)"

import boto3

client_ec2 = boto3.client('ec2', region_name=INSTANCE_REGION)
r = client_ec2.describe_instances(InstanceIds=[INSTANCE_ID])

ip = r['Reservations'][0]['Instances'][0]['PublicIpAddress']

client_route53 = boto3.client('route53')
client_route53.change_resource_record_sets(
    HostedZoneId=DOMAIN_ZONE,
    ChangeBatch={'Changes': [{
        'Action': 'UPSERT',
        'ResourceRecordSet': {
            'Name': URL,
            'Type': 'A',
            'TTL': 300,
            'ResourceRecords': [{'Value': ip}]
        }
    }]}
)

그 다음 이 스크립트를 부팅시 실행되도록 설정한다. 여러가지 방법이 있지만 난 crontab을 이용하였음.

crontab -e

@reboot sleep 30 && /usr/bin/python3 /home/ec2-user/route53/update.py

경로 등은 알아서 수정해주자.
난 혹시 몰라서 30초 딜레이를 줬는데 안줘도 될 수도.

1번 테스트 해봤는데 일단 잘 된다. ㅎㅎ

참고
Auto-Register EC2 Instance in AWS Route 53

Posted by iolate

댓글을 달아 주세요

  1. 2019.10.01 14:36 Bhan  댓글주소  수정/삭제  댓글쓰기

    AWS EC2에 해놀 올릴 수 있나요? 혹시 가능한지 여부랑 성능 궁금해서 문의합니다.

    • 2019.10.05 13:07 신고 BlogIcon iolate  댓글주소  수정/삭제

      사용하시는 os에 따라서 조금 달라질 수는 있지만, 가능합니다.

      다만 IAM 유저 생성해서 credential 은 만들어 넣어주셔야 합니다

AWS Lambda 에서 Python 을 쓰면서, AWS 서버에 설치되지 않은 패키지를 사용할 때에는 함수에 포함해서 업로드를 해줘야한다.

 

pip -t 옵션으로 패키지 다운로드 경로를 지정해서 람다 함수 루트에 패키지를 다운받아주면 되지만,

이 경우 디렉토리가 지저분해짐.

 

해결책은 당연하게도, 임의의 폴더를 만들어서 패키지를 다운받고, 해당 경로를 환경변수에 추가해주면 된다.

mkdir packages
# python3 -m pip install [package name] -t ./packages/
python3 -m pip install -r requirements.txt -t ./packages/

 

이 후 Python 핸들러 함수에서 환경변수 추가하기 위한 코드를 파일 최상단에 삽입

import sys, os
sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'packages'))

 

이렇게 하고 packages 폴더는 잊어버리거나 .gitignore 등에 추가해주면 된다.

 

+ 배포 스크립트

AWS Lambda 로 업로드 할때, 난 아래와 같은 스크립트를 만들어서 사용함. (2zip.sh)

 

동작 방식은

1. 몇몇 예외 파일을 제외하고 압축파일 생성

2. aws-cli 를 이용하여 업로드 후

3. 해당 압축파일 삭제

 

#!/bin/bash
LAMBDA_FUNC="Lambda 함수 이름"
zip -rq lambda.zip . -x *__pycache__* 2zip.sh env.sh requirements.txt CONFIG
aws lambda update-function-code --function-name $LAMBDA_FUNC --zip-file fileb://lambda.zip > /dev/null 2>&1
rm lambda.zip

-x 옵션의 인자 등은 상황과 필요에 따라 적절하게 수정을 해주자.

Posted by iolate
TAG AWS, lambda, Python

댓글을 달아 주세요

이건 정리용.


1. Root CA 생성

# CA private key 생성
openssl genrsa -out ca.key 2048

# CA request 생성
openssl req -new -key ca.key -out ca.csr -subj "/C=KR/O=TIM Lab/CN=My VPN CA"

# CA 인증서 생성
echo "basicConstraints = critical, CA:TRUE
subjectKeyIdentifier = hash
keyUsage = digitalSignature, keyCertSign, cRLSign" > ca.ext

openssl x509 -req -days 3650 -extfile ca.ext -set_serial 1 -signkey ca.key -in ca.csr -out ca.crt

# 필요없는 설정파일과 csr 제거
rm ca.ext ca.csr


2. ta.key, dh2048.pem 생성 

openssl dhparam -out dh2048.pem 2048
openvpn --genkey --secret ta.key


3. 서버용 인증서 생성

# private key 생성
openssl genrsa -out cert.key 2048

# csr 생성
openssl req -new -key cert.key -out cert.csr -subj "/C=KR/O=My Organization/CN=VPN Server"

# CA 인증서/키로 인증서 생성
echo "basicConstraints = critical, CA:FALSE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
keyUsage = digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth" > cert.ext

openssl x509 -req -days 3650 -extfile cert.ext -CA ca.crt -CAcreateserial -CAkey  ca.key -in cert.csr -out cert.crt

# 필요없는 설정파일과 csr 제거
rm cert.ext cert.csr

# 서버 인증서, 키 등 이동 / 복사
cp ca.crt /etc/openvpn/ca.crt
cp cert.key /etc/openvpn/server.key
cp ta.key /etc/openvpn/ta.key
mv cert.crt /etc/openvpn/server.crt



4. 클라이언트용 인증서 생성

사실 서버 인증서 생성과 큰 차이 없다. X.509 의 설정파일 내용 정도?
# private key 생성
openssl genrsa -out cert.key 2048

CERT_NAME="Gildong Hong"

# csr 생성
openssl req -new -key cert.key -out cert.csr -subj "/C=KR/O=My Organization/CN=$CERT_NAME"

# CA 인증서/키로 인증서 생성
echo "basicConstraints = critical, CA:FALSE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
keyUsage = digitalSignature" > cert.ext

openssl x509 -req -days 3650 -extfile cert.ext -CA ca.crt -CAcreateserial -CAkey  ca.key -in cert.csr -out "clients/$CERT_NAME.crt"

# 필요없는 설정파일과 csr 제거
rm cert.ext cert.csr



5. ovpn 설정파일 만들기

exec 3> VPN.ovpn

echo "client
remote SERVER_HOST PORT

dev tun
proto udp
resolv-retry infinite
nobind
cipher AES-256-CBC
auth SHA256
key-direction 1
persist-key
persist-tun
remote-cert-tls server
verb 3

;redirect-gateway def1 bypass-dhcp
;auth-user-pass
" >&3

printf "\n\n<ca>\n" >&3
cat ca.crt >&3
printf "</ca>\n\n<tls-auth>\n" >&3
cat ta.key >&3
printf "</tls-auth>\n\n<cert>\n" >&3
cat "clients/$CERT_NAME.crt" >&3
printf "</cert>\n\n<key>\n" >&3
cat cert.key >&3
printf "</key>" >&3

exec 3>&-


Posted by iolate

댓글을 달아 주세요

OpenVPN 은 기본적으로 사용자별로 인증서를 생성해서 연결하도록 하고 있다.


그러다보니 설정파일에 ca, tls-auth, cert, key 4개의 파일이 추가로 따라다니게 되는데 관리하기 조금 번거로운 면이 있다.

물론 각각 ovpn 파일안에 임베딩해버릴 수 있지만...


아이디, 비밀번호로 로그인하는 방법이 있길래 진행해보았다.


먼저 OpenVPN 서버 설정에서 아래 두 문구를 추가한다.

client-cert-not-required
auth-user-pass-verify "/etc/openvpn/userauth/verify.sh" via-file

첫번째 줄은 클라이언트 인증서가 필요없게 하는거고, 두번째줄은 비밀번호를 체크할 스크립트를 지정한다.

저 파일은 내가 만들어줘야하며, 경로는 어디두던 크게 상관없음.


다만 user nobody / group nogroup 설정을 했을 경우 OpenVPN 데몬이 nobody / nogroup 권한으로 작동하기 때문에, 권한에 유의해주면 된다. 읽기 권한이나 실행 권한 등이 없으면 비밀번호 체크를 할 수 없다.

비밀번호 체크 과정에 root 권한이 필요하다면 권한을 낮추는 해당 설정을 제거해주자.


스크립트 경로 뒤의 via-file 은 OpenVPN 에서 사용자가 입력한 아이디와 비밀번호를 넘겨줄 방식을 정한다.

via-file 로 할 경우 임시 파일을 생성하면서

username
password

이렇게 두 줄로 된 파일을 생성한다.


(via-env 로 할 경우 환경변수에 넣어준다는데, 사용자명은 들어오는데 비밀번호는 어디있는지 모르겠더라...)



해당 스크립트에서 아이디와 비밀번호를 읽어서, 성공했다면 exit 0 을, 실패했다면 에러코드와 함께 프로그램이 종료되면 된다.



이제 비밀번호 체크를 위한 스크립트를 만들자.

방식은 다양하니 직접 만들면 되겠지만 내 스크립트를 참고 삼아 올려둠.


아래 URL 에 들어가보면 다른 스크립트들도 있다.


나는 user.pass 파일에

사용자명=SHA1비밀번호
사용자명=SHA1비밀번호

꼴로 저장을 해두고, 이를 검사하는 방식으로 작성하였다.


verify.sh 코드는 이렇게.

#!/bin/bash
passfile="/etc/openvpn/userauth/user.pass"
logfile="/var/log/openvpn/userauth.log"

username=`head -n 1 $1`
password=`head -n 2 $1 | tail -1`

hashed=`echo -n $password | sha1sum | awk '{print $1}'`
userpass=`cat $passfile | grep $username= | awk -F= '{print $2}'`

if [ "$userpass" = "$hashed" ]; then
        echo "`date +'%Y-%m-%d %H:%M:%S'` - auth success: $username" >> $logfile
#       echo "ok"
        exit 0
fi

echo "`date +'%Y-%m-%d %H:%M:%S'` - auth fail: $username" >> $logfile
#echo "not ok"
exit 1



그리고 client 설정 파일에는 cert 와 key 를 없애고, auth-user-pass 옵션을 추가해주면 된다.



----------

이 다음으로, Local 사용자 계정으로 로그인하는걸 시도해보았다.


보통 shadow 파일을 읽어서 비교를 많이 하던데, 나는 PAM Authentication 을 이용해보았다.

PAM 인증을 할때 root 이어야만 제대로 작동하는 것 같으니, 서버 설정에서 user nobody 옵션은 주석처리 해주자. (혹은 스티키 비트를 넣어주거나..)



PAM 인증을 하는 c 프로그램을 제작하였고, 로그를 남기기 위해 간단한 쉘 스크립트를 같이 이용하였음.

verify.sh

#!/bin/bash
pam_auth="/etc/openvpn/userauth/pam_auth"
logfile="/var/log/openvpn/userauth.log"

pam_result=`$pam_auth $1`
ret=$?

echo "`date +'%Y-%m-%d %H:%M:%S'` $pam_result" >> $logfile
exit $ret



pam_auth.c ( https://gist.github.com/iolate/a58b73a023b35d5f181814de2f4ffccd )

// gcc -o pam_auth pam_auth.c -lpam

#include <security/pam_appl.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

int custom_converation(int num_msg, const struct pam_message** msg, struct pam_response** resp, void* appdata_ptr) {
	// Provide password for the PAM conversation response that was passed into appdata_ptr
	struct pam_response* reply = (struct pam_response* )malloc(sizeof(struct pam_response));
	reply[0].resp = (char*)appdata_ptr;
	reply[0].resp_retcode = 0;

	*resp = reply;
	return PAM_SUCCESS;
}

int main(int argc, char *argv[]) {
	if (argc != 2) {
		fprintf(stderr, "Usage: %s [filepath]\n", argv[0]);
		exit(1);
	}
	
	FILE* fp;
	char* username = NULL;
	char* password = NULL;
	size_t len = 0;
	ssize_t read;
	
	fp = fopen(argv[1], "r");
	if (fp == NULL) {
		fprintf(stderr, "%s: Cannot open '%s'\n", argv[0], argv[1]);
		return 1;
	}
	
	read = getline(&username, &len, fp);
	if (read == -1) {
		fclose(fp);
		return 1;
	}
	username[strlen(username)-1] = '\0'; // remove LF
	
	read = getline(&password, &len, fp);
	if (read == -1) {
		fclose(fp);
		return 1;
	}
	password[strlen(password)-1] = '\0'; // remove LF
	
	fclose(fp);
	
	// PAM Authentication
	struct pam_conv conv = {custom_converation, password};
	pam_handle_t* pamh = NULL;

	int retval = pam_start("whoami", username, &conv, &pamh);

	if (retval == PAM_SUCCESS)
		retval = pam_authenticate(pamh, 0); // is user really user?

	//if (retval == PAM_SUCCESS)
	//	retval = pam_acct_mgmt(pamh, 0); // permitted access?

	if (retval == PAM_SUCCESS) {
		fprintf(stdout, "Authenticated - %s\n", username);
	} else {
		fprintf(stdout, "Not Authenticated - %s\n", username);
	}

	pam_end(pamh, 0);
	return retval;
}


pam_auth 를 컴파일하기 위해선 pam development 패키지가 필요하니 설치하고 컴파일 해주자.

Ubuntu 기준 아래의 방법으로 진행하면 됨.

sudo apt install libpam0g-dev
gcc -o pam_auth pam_auth.c -lpam



verify.sh 를 간단히 수정하면, 두가지 방식을 동시에 사용하는 것도 가능하다.


참고

https://forums.openvpn.net/viewtopic.php?t=24907

https://medium.com/@nqbao/openvpn-auth-user-pass-verify-example-8d99023f08f7


https://unix.stackexchange.com/a/153323

http://www.linux-pam.org/Linux-PAM-html/adg-example.html

Posted by iolate

댓글을 달아 주세요

Ubuntu 18.04 에 NIS 를 구성하여 사용하고 있었음.


설치 및 설정은 아래 링크를 참고.


Ubuntu 18.04 : NIS Server

(01) Configure NIS Server

(02) Configure NIS Client

(03) Configure NIS Slave


나는 Slave 서버는 없고, MERGE_PASSWD 와 MERGE_GROUP 옵션은 뭔지 잘 모르겠어서 하라는대로 하지 않았음.


위 방법으로 1대의 Master 와 여러대의 Client 를 구성하였는데, Client에서 NIS 계정으로 로그인할 경우 SSH 연결을 위해서 20초 가량이 걸리면서 연결이 제대로 안되는 문제가 발생.


ssh -vvv 옵션을 주고 연결을 하면


(생략)

debug1: Entering interactive session.

debug1: pledge: network

(여기서 약 20초 딜레이)

debug3: receive packet: type 80

debug1: client_input_global_request: rtype hostkeys-00@openssh.com want_reply 0

(생략)


이렇게 진행이 된다.


/var/log/auth.log 를 보면

sshd[15635]: pam_systemd(sshd:session): Failed to create session: Connection timed out


이런 식의 오류메시지가 남겨져 있음.


찾아보니 systemd-logind 에 IP Sandbox 기능이 있는데 이와 관련한 문제이며 이 기능을 꺼줘야 한다고 한다.

보안상의 문제로 이걸 끄면 대체로 IP 필터를 걸어줘라~ 라는 식으로 적혀 있던데 이 기능 자체가 새로 생긴 것 같아 보이고 필요성을 모르겠어서 그냥 비활성화만 하고 치움.



sudo vi /lib/systemd/system/systemd-logind.service
SystemCallArchitectures=native
LockPersonality=yes
#IPAddressDeny=any
FileDescriptorStoreMax=512


sudo systemctl daemon-reload
sudo systemctl restart systemd-logind


참고

https://github.com/systemd/systemd/issues/9431

https://askubuntu.com/questions/1031022/using-nis-client-in-ubuntu-18-04-crashes-both-gnome-and-unity/1064617#1064617

Posted by iolate

댓글을 달아 주세요



웹 ssh 클라를 찾다가 발견한 프로그램.


사용자인증 및 사용자에 따른 커넥션 설정에다가 SSH 는 기본이고 RDP와 VNC 까지 지원을 한다.

RDP 테스트를 해봤는데 매우 쓸만한 수준.

심지어 모바일까지 잘 지원을 한다!


tomcat 위에서 돌아간다는 점만 제외하면 정말 마음에 드는데.... tomcat 은 싫으니 docker 에다가 넣어버리자.


guacamole 는 커넥션을 유지하면서 서버 역할을 해주는 데몬과 프론트엔드 인스턴스 2개로 분리되어 있다.

docker에서 각각 guacamole/guacd (데몬), guacamole/guacamole (프론트) 이미지를 사용하면 됨.


사용자와 연결설정 저장 등을 위해 mysql 등의 DB를 사용하게 되고 보통 이것까지 docker 로 돌리지만, 난 내 DB에 연결할 것이므로 생략.


먼저 이미지를 받아온다.

docker pull guacamole/guacd
docker pull guacamole/guacamole


그리고 도커 이미지에서 mysql 테이블 생성을 위한 스크립트를 가져온다.

docker run --rm guacamole/guacamole /opt/guacamole/bin/initdb.sh --mysql > initdb.sql


사용자나 DB는 알아서 생성을 하고, 해당 스크립트로 DB 구성을 한다.

mysql -hhost -uuser -p db_name < initdb.sql


컨테이너 설정을 위해서 docker-compose 를 사용한다.

없다면 설치를 해주고.. 아래 내용으로 docker-compose.yml 파일을 만든다.

version: '3'
services:
  guacd:
    hostname: guacd
    image: guacamole/guacd
    restart: always

  guacamole:
    image: guacamole/guacamole
    restart: always
    ports:
      - 8080:8080
    links:
      - guacd
    environment:
      GUACD_HOSTNAME: guacd
      MYSQL_HOSTNAME: DB_HOST
      MYSQL_DATABASE: DB_DATABASE
      MYSQL_USER: DB_USER
      MYSQL_PASSWORD: DB_PASSWORD


그리고 아래 명령어를 치면 아래처럼 컨테이너가 생성됨!

docker-compose up -d
Creating network "guacamole_default" with the default driver
Creating guacamole_guacd_1 ...
Creating guacamole_guacd_1 ... done
Creating guacamole_guacamole_1 ...
Creating guacamole_guacamole_1 ... done


이제 http://서버주소:8080/gucamole 로 들어가면 로그인창을 볼 수 있다.


기본 계정(위 mysql 설정을 통해 자동 생성됨)은 ID: guacadmin / PW: guacadmin



nginx 등으로 라우팅을 해주면 편하게 쓸 수 있을 듯.

apache2 나 nginx 에서 프록시 설정은 https://guacamole.apache.org/doc/gug/proxying-guacamole.html 을 참고하자.



참고 URL:

https://pages.wiserain.com/articles/deploying-guacamole-using-docker/

https://guacamole.apache.org/doc/gug/proxying-guacamole.html

Posted by iolate

댓글을 달아 주세요

  1. 2020.07.27 10:56 손님  댓글주소  수정/삭제  댓글쓰기

    무조건 따라하는 초보이다 보니 에러가 생겨버리면.. 멍 때리네요.
    VM115:1 POST http://10.xxx.xxx.xxx:8000/guacamole/api/tokens 500
    위와 같은 에러가 생기네요.
    시간 나실때 답변 부탁드립니다.

Win Server 2012 + Hyper-V 조합으로 쓰다가 도저히 불편해서 결국 Host 를 Linux 계열로 밀어버리는 대 공사 진행.


Ubuntu 18.04 + KVM 조합으로 결정했다.

Host 에서는 no GUI 로, SSH를 통해 설치 및 사용하고, KVM 가상머신 생성 및 설정은 X11 forwarding 을 통해 진행함.



KVM 설치

sudo apt install qemu-kvm libvirt-bin bridge-utils ubuntu-vm-builder

# GUI manager
sudo apt install virt-manager



이후 VM 관련 작업을 할때 매번 sudo 를 이용하고 싶지 않다면, 관련 그룹에 계정을 추가해준다.


그냥 설치만 해도 내 사용자 계정이 libvirt 그룹에 자동으로 추가되던데, 다른 계정을 이용했거나 필요에 따라 진행.


보통 libvirt, kvm, libvirtd 3개 그룹에 집어넣던데 환경에 따라... 난 이미 libvirt 그룹엔 속해져있었고 libvirtd 그룹은 생성이 안되어 있어서, kvm 에만 추가해두었다,

sudo adduser $(id -un) libvirt
sudo adduser $(id -un) kvm

# 나의 경우 libvirtd 그룹은 없었음
# sudo adduser $(id -un) libvirtd


가상머신 설치

가상머신 설치용 이미지나, 디스크는 기본적으로 /var/lib/libvirt/images 경로를 참조하고 사용한다. 필요하면 바꿔주면 되겠지만, 난 귀찮아서 그대로 사용, 설치 전 iso 이미지를 저기다가 넣어주었다.


커맨드라인으로 생성하고 관리하는 방법도 있는데, 난 X11 forwarding 을 사용.

ssh 연결시에 -X 옵션을 넣어주고 연결한다.


* Mac 이라면 XQuartz 를 설치해줘야한다.

또한 XQuartz 실행시에 키보드가 한글로 되어 있다면 이후에 계속 키 입력이 이상하게 되니 주의해주자.

그리고 연결 끊고 재연결시엔 독에서 XQuartz 를 직접 끄고 다시 연결해줘야하는 듯...


ssh -X user@host

$ virt-manager



그럼 이런 창이 뜬다. 이 상황에서 가상머신 생성, 설정, 콘솔보기 등을 할 수 있음.


생성은 알아서 하는걸루.. 별거 없다.



네트워크 관련 설정

브릿지 NIC 생성 및 사용하기

기본적으론 virbr0 란 이름으로 NAT NIC 만 생성해준다.


1. br0 인터페이스 생성

Ubuntu 17? 18? 부터 네트워크 인터페이스 관리를 위해 netplan 패키지를 이용한다.

설정 파일 경로는 /etc/netplan/


적당히 60-kvm.yaml 이란 이름으로 만들어서 br0 네트워크 인터페이스를 생성해준다.

eno1 은 브릿지 하려는 NIC 이름. br0 도 필요하다면 이름을 바꿔줄 것.


sudo vi /etc/netplan/60-kvm.yaml
network:
  version: 2
  bridges:
    br0:
      dhcp4: false
      interfaces: [eno1]
# 설정 적용
sudo netplan apply


적당한 경로에 아래 내용을 가진 br0.xml 파일을 만들고 그 밑 명령어로 KVM NIC를 설정해준다.

<network>
        <name>br0</name>
        <forward mode='bridge'/>
        <bridge name='br0'/>
</network>
virsh net-define br0.xml
virsh net-start br0
virsh net-autostart br0


이 후 아래와 같이 확인할 수 있다.

virsh net-list --all
 Name                 State      Autostart     Persistent
----------------------------------------------------------
 br0                  active     yes           yes
 default              active     yes           yes


이제 NIC 설정에 "Virtual network 'br0' : Bridge network 가 나타나서 사용할 수 있다.

virt-manager 로 새 VM을 만들땐 NIC 를 하나밖에 선택을 못할텐데,

마지막 단계에 "Customize configuration before install" 체크박스가 있고, 이걸 체크하면 뜨는 설정 창에서 Add Hardware 를 통해 NIC 를 추가할 수 있다.






NAT 고정 IP 설정하기

기본으로 생성되는 NAT NIC 는 IP 를 DHCP 로 할당한다.


가상머신에서 static ip 를 설정해줘도 되겠지만, host에서 특정 Mac 주소에 대해 고정 IP 를 할당하는 방법



virsh net-edit default
# 처음이라면 에디터를 선택하라고 뜰텐데 편한걸 선택하면 된다. 난 vim basic.

<ip address='192.168.122.1' netmask='255.255.255.0'>
    <dhcp>
      <range start='192.168.122.2' end='192.168.122.254'/>
      <host mac='52:54:00:FF:FF:FF' name='NAME' ip='192.168.122.XXX'/>
    </dhcp>
  </ip>
</network>


dhcp 부분을 찾아서 위와 같이 특정 맥 어드레스에 대해 아이피 주소를 할당해준다.


이 후 아래 명령어를 통해 변경사항 적용.



virsh net-destroy default
virsh net-start default


Posted by iolate

댓글을 달아 주세요

  1. 2020.05.18 15:49 BlogIcon 마음에 들어  댓글주소  수정/삭제  댓글쓰기

    잘 배우고 갑니다

  2. 2020.06.17 13:13 hw  댓글주소  수정/삭제  댓글쓰기

    혹시 host가 아닌 vmware Ubnuntu 안에 kvm 을 설치하려면 어떻게 해야할까요? kvm-ok에 CPU가 지원하지 않는다고 나오는데 UBUNTU 재설치로 해결할 수 있나요?

최근에 달린 댓글

최근에 받은 트랙백

글 보관함