カテゴリ:13.実際にやってみる > 13.3.2 Linux(アプリ)

■SMTPで単純なメールサーバを設定してみる。

メールアカウントは以下とする。
user1@example.com

(1)postfixの設定
①インストール
#yum install -y postfix

②main.cfの設定
# vi /etc/postfix/main.cf

myhostname = mx.example.com ※myhostnameやmydomainを指定しなくても可能ではあるが、あちこちでここで設定した値を$myhostnameなどと使っている。なので、設定しておこう 
mydomain = example.com
inet_interfeces=all
mydestination = $myhostname localhost.$mydomain $mydomain ※  $mydomainが含まれているものにしておこう。
mynetworks = 192.168.0.0/24 ←自分のグローバルIPアドレスを含むNWに変更
home_mailbox = Maildir/

sed(stream editor)で置換した方が早そうだ。
sedで流し込む場合は以下

sed -i /etc/postfix/main.cf \
-e "/#myhostname = host.domain.tld/a myhostname = mx.example.com" \
-e "/#mydomain = domain.tld/a mydomain = example.com" \
-e "/#inet_interfaces = all/ s/^#//" \
-e "/^inet_interfaces = localhost/ s/^/#/" \
-e "/^mydestination/ s/^/#/" \
-e "/#mydestination = \$myhostname, localhost.\$mydomain, localhost, \$mydomain\$/ s/^#//" \
-e "/#mynetworks = hash:\/etc\/postfix\/network_table/a mynetworks = 192.168.0.0\/24" \
-e "/#home_mailbox = Maildir/ s/^#//"

【補足】
・-i 上書き保存する。
・-eで複数の変換ができる。
・aをつけると、指定した行の後ろに追加(add)できる。
・sed -e 's/^#//g' でコメントアウトを外す
・^は行の先頭という意味
・行末に\$を入れているのは、上の^と逆で、行末を指定している。
・\/としたのは、文字列に/が入っているから。\で打ち消している。
・-e "/^mydestination/ s/^/#/" \ のところは、先頭に#を入れるだけなので、全部書く必要はないので、先頭のmydestinationだけにした。というか、全部書くと$が特殊文字なので、うまくいかなかった。\でエスケープすればいいだろうが…

(2)Dovecotの設定
Dovecotがインストールされているかの確認
yum list dovecot
入っていなかったらインストール
yum install -y dovecot

・設定ファイルの編集
vi /etc/dovecot/dovecot.conf

実は、設定変更は不要
protocolsで、imap pop3 などプロトコルを設定できるが、デフォルトのままとする。

vi /etc/dovecot/conf.d/10-mail.conf

mail_location = maildir:~/Maildir
→アンコメント + メールフォルダの場所を指定

vi /etc/dovecot/conf.d/10-auth.conf

disable_plaintext_auth = no
→アンコメントし、noに変更: プレーンテキストでのID PASSやり取りを許可

vi /etc/dovecot/conf.d/10-ssl.conf
ssl = no
→ssl を noに変更 SSL必須を解除

systemctl start dovecot
systemctl enable dovecot

■ユーザの作成
useradd -s /sbin/nologin user1
passwd user1

以上である。

これで、クライアントソフトでメールを送受信できるはず。

■メール設定の流し込み
以下でいいと思うが、うまくメールが送れないので、要確認。実際のクライアントソフトを入れればうまくいくかもしれないが・・・
#メール設定
#postfixの設定
yum install -y postfix

#main.cfの設定
cp /etc/postfix/main.cf /etc/postfix/main.cf.org
sed -i /etc/postfix/main.cf \
-e "/#myhostname = host.domain.tld/a myhostname = mx.sec.dom" \
-e "/#mydomain = domain.tld/a mydomain = sec.dom" \
-e "/#inet_interfaces = all/ s/^#//" \
-e "/^inet_interfaces = localhost/ s/^/#/" \
-e "/^mydestination/ s/^/#/" \
-e "/#mydestination = \$myhostname, localhost.\$mydomain, localhost, \$mydomain\$/ s/^#//" \
-e "/#mynetworks = hash:\/etc\/postfix\/network_table/a mynetworks = 0.0.0.0\/0" \
-e "/#home_mailbox = Maildir/ s/^#//"
systemctl restart postfix

#Dovecotの設定
yum install -y dovecot
#10-mail.confアンコメント
cp /etc/dovecot/conf.d/10-mail.conf /etc/dovecot/conf.d/10-mail.conf.org
sed -i /etc/dovecot/conf.d/10-mail.conf -e "/#   mail_location = maildir/ s/^#//"

#10-auth.confの設定
cp /etc/dovecot/conf.d/10-auth.conf /etc/dovecot/conf.d/10-auth.conf.org
sed -i /etc/dovecot/conf.d/10-auth.conf \
-e "/#disable_plaintext_auth = yes/a disable_plaintext_auth = no" \
-e "/#disable_plaintext_auth = yes/ s/^#//"

#10-ssl.confの設定
cp /etc/dovecot/conf.d/10-ssl.conf /etc/dovecot/conf.d/10-ssl.conf.org
sed -i /etc/dovecot/conf.d/10-ssl.conf \
-e "/ssl = required/a ssl = no" \
-e 's/ssl = required/#ssl = required/g'
systemctl start dovecot
systemctl enable dovecot


----------以下はAWSでやろうと思ったが、セキュリティ対策をしないシンプルなSTMPだと送受信ができないようだった。なので、最後まで行けていない。ローカルに立てるように変更してしまった。単なるメモである。

◆DNSサーバ
DNSサーバの設定が必要。AWSでは、DNSの名前解決をさせるために、セキュリティグループでDNSのポートを空ける必要があるよね?

DNS(UDP)とDNS(TCP)を、全てのポート、全てのソース(0.0.0.0/0)で空ける。

■メールサーバ
EC2でやりたいので、以下の手順でやってみるか
https://qiita.com/ghogho-seki/items/e79cc3d3a98fba900dfc

※EC2だと、迷惑メール防止のためにいろいろと制限があり、結構難しいかも。
※apacheなどは、起動さえすれば、デフォルトページが見える。だが、Postfixの場合は、そもそもlocalhostからしか受け付けない設定なので、main.cfを変えないとそもそも動かない。

(1)環境の確認
sub.momiji.pwドメインのメールサーバを構築する。
google.co.jpのようなものとイメージしてもらいたい。

メールアドレスは、user1@sub.momiji.pw
このメールアドレスに、自分のPCやWebメールと送受信してみよう。

今回もAWSでやってみる。
なので、AWSでセキュリティポリシーを空けておく。インバウンドとアウトバウンドの両方かな?

(2)Postfixの設定
①インストール
・Postfixが入っているかを確認・・・すでに入ってる

#yum list postfix
・・
postfix.x86_64  2:2.10.1-6.amzn2.0.3   installed

・自動起動もONになっている
# systemctl is-enabled postfix
enabled

②設定ファイルの設定
設定ファイルは/etc/postfix/main.cf
では、このファイルを設定していこう。設定するところは結構ある。全部設定しないと動かないのかは不明

今回設定したのは、以下だけ。このあと、解説を入れる。
# vi /etc/postfix/main.cf

myhostname = mx.sub.momiji.pw 
mydomain = sub.momiji.pw
inet_interfeces=all
mydestination = $myhostname localhost.$mydomain $mydomain
mynetworks = 153.176.49.0/24 ←自分のグローバルIPアドレスを含むNWに変更
home_mailbox = Maildir/

 
# vi /etc/postfix/main.cf

変更するところだけを記載する。
・ myhostname = mx.sub.momiji.pw  ←メールサーバのFQDN …これが、この設定ファイルで記載される $myhostname の値になる。#でコメントアウトされているので変更
・ mydomain = sub.momiji.pw ←メールのドメイン・・・同様に、これが、この設定ファイルで記載される$mydomain の値になる。
・ inet_interfeces=all ←インターフェースを変更
※設定としては、113行目のコメントを外し、116をコメントアウトする。つまり、inet_interfeces をlocalhostからallに変更する。

・mydestination = $myhostname localhost.$mydomain $mydomain  $mydomainも加えた方がいいので、コメントアウトをうまく活用して、自分のドメインを許可する。

・mynetworksで、信頼するネットワークを指定する。ここで書いたhost やネットワークからのメールを処理する。なので、踏み台にされないためにも、限定すべきである。
 普通は、192.168.1.0/24などとサブネットを書く。AWSで試験的にテストするのであれば、自分のグローバルIPアドレスを書けばいいだろう。
 mynetworks=203.0.113.24/32
153.176.49.55
・home_mailbox = Maildir/
※コメントを外す。メールボックスでのメールの保存形式には、mbox形式とMaildir形式がある。mbox方式は古くからある方式で。一つのファイルで管理する。Maildirは一つずつのファイルとして管理
https://go-journey.club/archives/9377

--------これ以降はオプション。必須ではない。

#relay_domains = $mydestination
→中継処理、たとえば、外部メールサーバから内部メールサーバに転送するような場合の設定(オプション)。デフォルトではコメントアウトされている。

・myorigin = $mydomain
→@より左側、たとえばuser1でメールを送った場合に、myoriginで記載した内容を補足し、user1@sub.momiji.pwとしてくれる。必要ならば ※コメントアウトをはずす
・smptd_banner = $myhostname ESMTP unknown
→使っているSMTPソフトの隠蔽。もちろん、myhostnameを、smptd_banner =の前に適切に設定しておかなければいけない。

・以下を3行追加
smtpd_recipient_restrictions =
permit_mynetworks
reject_unauth_destination # 追加

→メール送信リクエストを受けた際に、拒否するルールを記載。permit_mynetworksは別途定義するmynetworks以外のネットワークからのリクエストを拒否。reject_unauth_desctinationは宛先が不正(存在しないユーザへの配送リクエスト等)を受け付けない

・smtpd_sender_restrictions =
 reject_unknown_sender_domainなどで送信者チェックが行える。メールアドレスのFrom部分のチェックである。(詐称されたらチェックできないが)。

・message_size_limit = 10485760 # 追加 数値は任意
→メールボックスのマックスサイズ

◆Submissionポート有効化
→多くのプロバイダでは、OP25Bにより、25番で送れないことがほとんど。なので、設定しないと実行上は難しいだろう。

vi /etc/postfix/master.cf
submission inet n - n - - smtpd
→コメントアウト解除 サブミッションポートでの配送を許可

-o smtpd_sasl_auth_enable=yes
→アンコメント: SMTP認証を有効化
 
※SASL(Simple Authentication and Security Layer)

yum -y install cyrus-sasl
→SMTP認証セットアップ
systemctl start saslauthd
→起動

postfix の再起動が必要

③書式チェックは以下。これでエラーが出なければチェックOK
#postfix check

設定が終わったら、postfixの再起動

④ユーザの作成

※/etc/skelにて、個別ではなく雛形を作ることが一般的のようだが、どうやら、この手順は不要のようだ。自然にフォルダも作成される。
mkdir -p /etc/skel/Maildir/{new,cur,tmp}
chmod -R 700 /etc/skel/Maildir/

useradd -s /sbin/nologin user1
→user作成(sshログインはできないユーザとして作成)
passwd user1
→パスワード設定

(2)Dovecotの設定
以下がシンプル
https://dev.classmethod.jp/cloud/aws/mail_server_with_postfix_and_dovecot/

Dovecotがインストールされているかの確認
yum list dovecot
入っていなかったらインストール
yum install -y dovecot

・設定ファイルの編集
vi /etc/dovecot/dovecot.conf

実は、設定変更は不要
protocolsで、imap pop3 などプロトコルを設定できるが、デフォルトのままとする。

vi /etc/dovecot/conf.d/10-mail.conf

mail_location = maildir:~/Maildir
→アンコメント + メールフォルダの場所を指定

vi /etc/dovecot/conf.d/10-auth.conf

disable_plaintext_auth = no
→アンコメントし、noに変更: プレーンテキストでのID PASSやり取りを許可

vi /etc/dovecot/conf.d/10-ssl.conf
ssl = no
→ssl を noに変更 SSL必須を解除

systemctl start dovecot
systemctl enable dovecot

■ユーザの作成
useradd -s /sbin/nologin user1
passwd user1

AWSにて、110, 143ポートで外部から接続できるようにする。

■1.インストール
 yum -y install httpd
ただ、Linuxをインストールすると、デオフォルトでWebサーバが起動していることが多いだろう。入れ方にもよるが。(AWSは入っていないので、入れる必要がある)

・サービスを開始する
systemctl start httpd

・サービスの状態確認 (CentOS7)
systemctl status httpd→緑色で、active (running) になっていれば起動している。

・(おまけ)プロセスを、以下で見てみよう。
# ps -auwx | grep httpd
するとapacheユーザでたくさんのプロセスが起動している。これは、Webサーバに複数のアクセスがるので、それに対応するだめである。他のサービスではこれほどでない

・Webサーバが起動しているか、となりのPCから見てみよう。http://WebサーバのIPアドレス

→赤っぽい色のバーがついたApacheのTest Pageが見えれば動作している。

もしかすると、見えないかもしれない。
原因は、SELinuxが有効になっているのと、サーバのFirewallなどの設定などが入っているからだろう。($system-config-firewallで設定を解除すればいいだろう)

Firewallを開けるには、以下。
・httpを許可する
firewall-cmd --add-service=http --zone=public --permanent      
 ※--permanent によって、永続的にHTTPを開ける
・再起動
firewall-cmd --reload  
・確認
iptables -L -n | grep 80

※AWSの場合、インバウンドルールにhttp(80)を追加する。

■2.コンテンツ
コンテンツは/var/www/htmlに入れる

・デフォルトのTest Page
htmlコンテンツのありかは、/var/www/html である。
ただ、デフォルトのTest Pageだけは特別。
以下のconfファイルに設定が記載されている。
/etc/httpd/conf.d/welcome.conf
実際のコンテンツはこれ
/usr/share/httpd/noindex/index.html

■3.設定ファイル  httpd.conf
基本的には何も設定変更をしなくても動作する。なので、触る必要はない。

何点かコメント
・ServerRoot "/etc/httpd"  ←デフォルトのフォルダ。相対パスで記載されるの場合はこちらの配下
・Listen 80  ←接続を待ち受けるポート番号
・DocumentRoot "/var/www/html"  ←コンテンツを配置するフォルダ。なので、たとえば、http://www.example.com/の直下がこのフォルダになる。
・ファイルじゃなくてディレクトリが指定された場合には、以下のディレクティブのDirectoryIndexで指定されたページを開く。列挙することで、複数指定できる→このあとにも記載
 <IfModule dir_module>
    DirectoryIndex index.html
</IfModule>
※mod_dirというモジュールが、ここに書かれたファイルへリダイレクトする。なので、IfModule dir_moduleというディレクティブに記載がある。
https://httpd.apache.org/docs/2.2/ja/mod/mod_dir.html
・Directoryのディレクティブ
 いくつものDirectoryのディレクティブがある。Directoryで指定されたフォルダに関して(サブフォルダを含む)オプションの設定ができる。たとえば、一覧表示をするindexesを指定すると、一覧表示がされる。FollowSymLinksはシンボリックリンクを設定すると、そのフォルダにリンクされる。どちらも、セキュリティ的にあまりいいオプションとはいえない。
<Directory "/var/www/html">
   #  Possible values for the Options directive are "None", "All",
 ・・・
     Options Indexes FollowSymLinks
    
</Directory>
<Directory "/var/www/cgi-bin">
     AllowOverride None
     Options None
     Require all granted
</Directory>

■4.httpsにする場合
設定ファイルは以下
/etc/httpd/conf.d/ssl.conf  

■5.Webサーバのログ
(1)アクセスログ
/var/log/httpd/access_logに保存されている。
ログとしてはこんな感じ。
192.168.1.3 - - [08/Sep/2018:23:36:16 +0900] "GET /  HTTP/1.1" 403 4961 "-" "Mozilla/5.0 (Windows NT 6.3;・・・
先頭がアクセス元のIPアドレス
 
(2)エラーログ
同じフォルダのerror_log
※また、このフォルダはシンボリックリンクで/etc/httpd/logs/access_logからも見ることができる

■6.Basic認証とDigest認証の設定
以下に記載しました。
http://sm.seeeko.com/archives/22724259.html

■7.その他
(1)バージョンの確認
httpd -version
または、
rpm -qa | grep httpd でもいいだろう。

(2)ファイルの一覧表示/etc/httpd/conf/httpd.confの
Options Indexes FollowSymLinks で設定する
上記の場合は該当ディレクトリのファイル一覧が表示される
一覧表示されないようにする方法は、
①Indexesを消す
Options FollowSymLinks
②「-」を付ける  ※うまくいかなかった。
Options -Indexes FollowSymLinks 
※設定変更する場合は、もとの設定は#によるコメントアウトで残しておきましょう。
※基本は/var/www/htmlディレクトリの設定が関係しているはず
※デフォルトでは有効になっていたと思う。

(3)Apacheで日本語表記
文字コードを入れないと文字化けする場合、HTMLファイルの冒頭に、以下を入れましょう。→でも、入れなくても文字化けしないと思いますが・・・
<head>
  <meta charset="UTF-8">
</head>

(4)テストページ
①ファイル
index.htmlなどのファイルがないと、以下のテストページが表示される。
/usr/share/httpd/noindex/index.html
※もちろん変えることもできる。

②非表示にする
/etc/httpd/conf.d/welcome.conf.orgを設定する方法もあるだろうが、単純に名前を変えるか消してしまえばいい。
systemctl restart httpd

##### 1. 概要
2004年に登場したnginxですが、今ではApacheのシェアを超えたともいわれています。
読み方は「エンジンエックス」
Apacheと同じくWebサーバのソフトであるが、高速で軽量な点が特徴。利用されるケースが増えている。
LBとしても使える。・・・これがnginxの大きな意義の一つである。

LBの設定は以下が参考になる。とても簡単
https://www.nedia.ne.jp/blog/tech/2016/08/04/7938


##### 2. AWSへインストール
#yumでインストールするが、デフォルトだとエラーがでる
yum install nginx
 
#そこで、以下のようにしてインストール
amazon-linux-extras enable nginx1
yum -y install nginx

#バージョンの確認
nginx -v     # ==> nginx version: nginx/1.17.7

#自動起動の設定
systemctl enable nginx

#サービスの起動
systemctl start nginx

・ブラウザを立ち上げ、http://IPアドレス を指定
「Welcome to nginx!」と出て、Webサーバが起動していることが確認できる。

##### 3. 設定ファイル
(1)概要
・設定ファイルは以下。ここで、LBの設定などもできる。
/etc/nginx/nginx.conf

/etc/nginx/conf.d/default.conf

・コンテンツファイルの置き場所
 /usr/share/nginx/html

ここにたとえば、a.htmlというファイルを設置し、中身に「hello」と書けば、ブラウザでアクセスすると「Hello」と表示される。

・ログファイルの置き場所
/var/log/nginx/access.log 

(2)LBの設定
たとえば、CTFサーバ(203.0.113.12)がポート8000で動いていて、nginxをLBとして80番ポートで受けるとしよう。(AWSの場合、CTFサーバでLBのIPアドレスかつポート8000を許可する)
設定は単純である。
##設定ファイルを編集する
vi /etc/nginx/nginx.conf
##以下を追記する。実際には、locationに関連する3行だけである。
server {
  listen 80;
  ・・・・
  location / {
    proxy_pass http://203.0.113.12:8000;
  }
}
##再起動
systemctl restart nginx

設定は以上。めちゃくちゃ簡単だ!

MTAとしてはPostfixMUAとしてはdovecotなのは、長年変わらない。(※dovecotがメールボックスを持っているわけではなく、dovecotはユーザからのメール取得要求を受け付けるサービス)

どんな本でもいいので、一冊購入するといいですよ。
私は 秀和システム「はじめてのFedoraCore5」を買いました。
以下の内容は上記の本を参照してます。

1.sendmailの停止
service sendmail stop

2.Postfixのインストール
rpmpostfixをインストール

3.Postfix環境へスイッチ
alternatives --config mta
ここで、postfixを選択する。

4.main.cfの設定
vi /etc/postfix/main.cf
myhostname = ns1.network-exam.com 
mydomain = network-exam.com
inet_interfaces = all   ←利用するNIC
mydestination = $myhostname, localhost.$mydomain, $mydomain ←受信するドメインとホスト
mynetworks = 192.168.1.0/24, 127.0.0.0/8

postfixの設定で、メールボックスはMaildir方式が最近の主流で、メールが1通1ファイルになっている
home_mailbox = Maildir/ 

POP3サーバの設定
dovecotを利用します。

■1.DNSの設定に関して、全体像
(1)環境
・LinuxCL(クライアント)
・LinuxSV(DNSサーバ、Webサーバ)
・ドメインはexample.com
・LinuxCLから、www.example.comにドメイン名でアクセスする

(2)クライアント環境の確認
①名前解決の方法
/etc/nsswitch.confのファイルを見ると、dnsを使うことが記載されている。

# cat /etc/nsswitch.conf | grep hosts
#hosts:     db files nisplus nis dns
hosts:      files dns myhostname

※詳しくは以下
http://sm.seeeko.com/archives/15877466.html

②DNSサーバの指定
/etc/resolv.confにDNSサーバが記載されている。AWSの場合は、そのVPCの末尾2がデフォルトで設定されている。ちなみに末尾1はデフォルトGW
# cat /etc/resolv.conf | grep nameserver
nameserver 172.31.0.2

→キャッシュDNSサーバを構築するのであれば、このIPアドレスを、新設するキャッシュDNSサーバに変更する。コンテンツDNSサーバであれば、あえてしなくてもいいだろう。

■2.DNSサーバの設定
(1)設定の流れを解説する
①bindのインストール
②設定ファイルの設定
③サービスの起動
④動作確認

(2)BINDのインストールと確認
yum install -y bind
systemctl start named
systemctl status named
systemctl enable named
named -version

(3)設定ファイルの設定
cp /etc/named.conf /etc/named.conf.org
vim /etc/named.conf

・コメントアウト
// listen-on port 53 { 127.0.0.1; };

・設定次第
allow-query     { localhost; };
recursion no;

※1つ目はAWSなどで広く許可する場合には//でコメントアウト

・追加
zone "sub.momiji.pw" IN {
        type master;
        file "sub.momiji.zone";
};

zone "x.x.x.in-addr.arpa" IN {
        type master;
        file "reverse.zone";
};

※x.x.xのところはIPアドレスに応じて設定する

■3.ここからはもう少し丁寧に、というか詳しく解説
(1)インストールやら
・BINDのインストール
# yum install -y bind
・起動
# systemctl start named
・確認
# systemctl status named

・プロセスを確認しよう
# ps -aux | grep named
named      373  0.0  6.0 169256 60952 ?        Ssl  02:46   0:00 /usr/sbin/name  -u named -c /etc/named.conf

※脱線するがセキュリティ面で重要な話。先頭がnamedになっている。つまり、このサービスはrootではなくnamedが起動している。BINDに脆弱性があった場合に、root権限を乗っ取られたりしないようにこうしている。apacheなども同様。

CentOSでバージョンを見てみよう。
# named -version
BIND 9.11.4-P2-RedHat-9.1・・・
※日常的に使われるバージョンは9

※ rndc-confgenを使うと、鍵の生成などができる。デフォルトのままでいいと思う。

(2)設定してみよう
①デフォルトの/etc/named.conf をみる
デフォルトは以下である。hintのzoneしかないので、管理するドメインを追加していく必要がある。

options {
        listen-on port 53 { 127.0.0.1; }; ←ポートは53。この行を残すのであれば、自分の(つまりDNSサーバ)のIPアドレスを入れる。またはany
     ・・・
        directory       "/var/named";  ←デフォルトのディレクトリ。
     ・・・
        allow-query     { localhost; }; ←DNSクエリを受け付ける範囲。適切に設定する。anyか、この行そのものをコメントアウトでもいいだろう
      ・・・
       recursion yes; ←再帰問い合わせを受ける。キャッシュDNSサーバとして動作する。コンテンツDNSサーバの場合はnoにする。

zone "." IN {
        type hint;     ←typeがhintなので、ルートDNSサーバのこと
        file "named.ca";
};


②ルートヒントファイルをみてみよう
以下のファイルがそう
/var/named/named.ca

たとえば、以下などが入っている

l.root-servers.net.     518400  IN      A       199.7.83.42
m.root-servers.net.     518400  IN      A       202.12.27.33

※テストとして、自分で設定してもいい。ようは、本当のサーバじゃなくて自分が設定したサーバを指定するのだ

③実際に作ってみよう
momiji.pwドメインのDNSサーバはレジストラで管理してもらっている。そのDNSサーバはレジストラだ。私は、このドメインを管理できるので、サブドメインに関しては、自分が構築したDNSサーバに委任しよう

sub1.momiji.pw →ns1.sub1.momiji.pwというDNSサーバに委任

たとえてみよう。example.co.jpドメインの管理者は、co.jpからexample.co.jpドメインの管理を委任されている。
仮にexample.co.jpのNSがns1.example.co.jpとしよう。
私がmomiji.pwのDNSの管理者であり、sub1.momiji.pwのドメインの管理を委任する。そのとき、sub1.momiji.pwのNSがns1.sub1.momiji.pwという位置づけである。→このあたりに関しては後半に詳細を記載。

(3)では、設定ファイルを作成する。
①named.conf
・まず、named.confのバックアップを取る
# cp named.conf named.conf.org

lsでみると、グループがrootになってしまっているので、変えよう
# ls -la | grep named
# chgrp named named.conf.org

・では、named.confファイルを編集する。
もともとある zone "." をコピーして作ろう
zone "sub.momiji.pw" IN {
        type master;
        file "sub.momiji.zone";
};
listen-on port 53 の行は、自分のIPアドレスを入れる。プライベートでいい?
いったん、コメントアウトで消しておこう。
また、キャッシュDNSサーバではないので、以下の再帰問い合わせはno
      recursion no
そして、外部に公開するわけなので、localhostに限定しているQueryの許可を、コメントアウトで外す。
 allow-query     { localhost; };
 
・構文のチェック
# named-checkconf /etc/named.conf

named-checkconf で構文のチェック。コマンドを実行して何もエラーがなかったらOK

②zoneファイルの作成
/var/named/named.localhostがサンプルになるだろう
これをもとに作成していく。
cp でファイルをコピーすればいいが、rootで実行するとグループがrootのままであるだろう。なので、chgrpでnamedのグループにする
#chgrp named sub.momiji.zone

zoneファイルの内容は、このあとにしっかりと記載した。

構文をチェックしましょう。
#named-checkzone sub.momiji.pw /var/named/sub.momiji.zone
 
③DNSが動作したかチェックしてみよう
もう少し仕上げをします。
AWSの場合、UDP53を許可しましょう。

・nslookup で確かめてみよう
>nslookup

>server x.x.x.x ←構築したDNSサーバに問い合わせ先を変更

> www.sub.momiji.pw
サーバー: ・・・
Address:  ・・・

名前:    www.sub.momiji.pw
Addresses:  ::1
          3.113.x.x   ←このようにIPアドレスを引くことができた。

レジストラのDNSの設定のTTLが反映されると、DNSサーバを指定しなくても、普通にこのドメインを引くことができるだろう。ブラウザでURLにwww.sub.momiji.pwを指定して閲覧することも可能だ。

さて、ここまでの設定でも無事に動いたと思う。理解する目的だけであればそれで十分だが、実際には以下の設定も必要

④逆引きファイルの作成
同様に実施。正引きのファイルをコピーするといいだろう

以下は実際にやってみた様子
以下を追加
zone "113.0.203.in-addr.arpa" IN {
        type master;
        file "reverse.zone";
};
サブネットマスクは24ビットではないかもしれないが、気にせず24ビットと思ってIPアドレスを逆から並べる。
reverse.zoneは正引きファイルをコピーする。
そして、NS以外のAレコードを消して、PTRにする。
こんな感じ
        IN NS   ns1.sub.momiji.pw.
53     IN PTR  ns1.sub.momiji.pw.
53     IN PTR  www.sub.momiji.pw.
サービスを再起動し、チェックをする
以下のエラーがでる。が、いちおう、逆引きはできているような感じだ。
named-checkzone sub.momiji.pw /var/named/reverse.zone
zone sub.momiji.pw/IN: NS 'ns1.sub.momiji.pw' has no address records (A or AAAA)
zone sub.momiji.pw/IN: not loaded due to errors.

⑤ループバックの設定
特に設定は不要です。ループバックのような、インターネットに出るまでもない情報を保持しておきます。
ループバック設定などは以下がincludeされているので、追記する必要はない(、と思う)
include "/etc/named.rfc1912.zones";

(5)その他の設定
①キャッシュDNSサーバを作るとき
named.confの設定で、recursion yesにすると再帰問い合わせをする。
※再帰とキャッシュするかは別のような気がするが、基本的には同時進行と考えてほしい。

(女性)キャッシュDNSサーバはどれだけの時間、キャッシュを持つのですか?

反復問い合わせをしたコンテンツDNSサーバのTTLに依存する。どれだけキャッシュするかはキャッシュDNSが決めるのではなく、コンテンツDNSサーバが決めている。
また、caching-nameserverのモジュールを入れてもいいようだが、もう少し調査が必要だ。

(6)Linuxでのnslookup
digまたはhostコマンドを使う。 hostコマンドは情報がシンプルなので、見やすいと思う。一応、nslookupも使えるが、今後の開発はないので使わない。
dig @192.168.1.53 www.example.com
     ↑@でDNSサーバを指定  ↑引きたいホスト
 最後に+norecurse を付けると、再帰ではなく反復問い合わせをする。なので、キャッシュしないDNSの名前解決をしてくれる。

host  www.example.com 192.168.1.53
    ↑引きたいホスト   ↑DNSサーバを指定  
 host -r ・・・ として、rオプションを付けると、反復問い合わせをする

・余談であるが、Windowsおのnslookupの場合、debugオプションをつけると、TTLなども確認できる。

(7)セカンダリDNSサーバ
・ゾーンファイルの設定
 type slaveに設定、masters プライマリマスタサーバのIPアドレスを指定
 fileに、転送された情報を保持するファイルを記載。ファイルを作る必要はない。ただし、フォルダのアクセス権で、namedユーザが書き込めるようにしておく
 ※補足すると、デフォルトのnamed.confの設定を使う場合は、listen-on portのIPアドレスを変更(またはこの行をコメントアウト)、recursion noとして再帰問い合わせを禁止する、allow-queryをコメントアウトするなどして、他のホストから問い合わせできるようにする。
・上位ゾーンのサーバに、NSレコードを追加する
 
(8)DNSの委任
たとえば、example.comの場合、.comのDNSサーバは、example.comドメインのDNSサーバにドメイン管理を移譲する。そのことを書くために、自分のDNSサーバにexample.comのNS情報を書く
また、example.comドメインのDNSサーバにも、NSレコードでDNSサーバの情報を書く。
つまり、.comのサーバとexample.comのサーバに同じことを書いている
→なので、example.comのサーバにはNSレコードはなくてもいいのではないかとも思う。いくつかトラブルがあるかもしれないが…。

以下がとても参考になる。
https://www.atmarkit.co.jp/ait/articles/1501/15/news008.html

なので、今回は以下である。
①momiji.pw を管理しているレジストラでの設定
sub.momiji.pw. IN NS ns1.sub.momiji.pw.
ns1.sub.momiji.pw. IN A 203.0.113.53

→Value Domainを使っているので、構文がちょっと違う(もちろん覚える必要はない。単なるメモ)
ns sub ns1.sub.momiji.pw.
a ns1.sub 203.0.113.53

②権限移譲されたDNSサーバでの設定(sub.momiji.pwのゾーンファイル)
上記の①と全く同じことを書くのであるが、一般的には
以下のような省略形になる。
   IN NS ns1.sub.momiji.pw.
ns1    IN A 203.0.113.53

最終系はこんな感じ
$TTL 1D
@       IN SOA  ns1.sub.momiji.pw. mail.sub.momiji.pw. (
                                        2020010104      ; serial
                                        1D      ; refresh
                                        1H      ; retry
                                        1W      ; expire
                                        3H )    ; minimum
        IN NS   ns1.sub.momiji.pw.
ns1     IN A    203.0.113.53
www     IN A    203.0.113.53

--------以降は、流しこんで設定するための環境
これまで述べたことと基本的に同じである。
最低限の流し込みであれば、以下。
やっていることは、以下である。
・bindのインストール、サービスの起動
・www.aa.domのドメインのDNSサーバ
・正引きのaa.zoneしか作成していない。(逆引きやループバックは未作成。ループバックは不要だけどね)
・この設定だけでも、コンテンツDNSサーバおよび、キャッシュDNSサーバとして機能する。※初期設定がrecursion yesであるため。
 →たとえば、別のPCのDNSサーバとして、このDNSサーバを指定すれば、yahooなどを名前解決してくれる。

sudo -i
yum install -y bind
systemctl start named
systemctl status named
systemctl enable named
named -version

cp /etc/named.conf /etc/named.conf.org

sed -i /etc/named.conf \
-e "/listen-on port 53/ s/^/\/\//" \
-e "/allow-query/ s/^/\/\//" \
-e "$ a zone \"aa.dom\" IN {\n\ttype master;\n\tfile \"aa.zone\";\n};"

named-checkconf /etc/named.conf

echo "\$TTL 1D" > /var/named/aa.zone
sed -i /var/named/aa.zone \
-e '$ a @       IN SOA  ns1.aa.dom. mail.aa.dom. (' \
-e '$ a \\t\t\t2020010904      ; serial' \
-e '$ a \\t\t\t1D      ; refresh' \
-e '$ a \\t\t\t1H      ; retry' \
-e '$ a \\t\t\t1W      ; expire' \
-e '$ a \\t\t\t3H )    ; minimum' \
-e '$ a \\t\IN NS   ns1.aa.dom.\nns1     IN A    203.0.113.53\nwww     IN A    203.0.113.80'

systemctl restart named
dig @127.0.0.1 www.aa.dom
host www.aa.dom 127.0.0.1

■流し込み2 ドメインを正規のもので実施した場合
以降はprivate記事
続きを読む

(1)FTPサーバのインストールと起動
①インストールと起動
yum -y install vsftpd
systemctl start vsftpd
systemctl enable vsftpd

1行目がインストール
2行目がサービス起動
3行目が起動時の自動起動設定

②状態確認
cat /etc/passwd | grep ftp
ls -la /var | grep ftp

※インストールすると、FTPユーザとして、ftpが作成されている。これは、anonymousでログインしたときのユーザ
※/var/ftpがanonymousのカレントフォルダ

・バージョンの確認
vsftpd -v
vsftpd: version 3.0.2
古いバージョンは脆弱性があるので注意
https://engineeringnote.hateblo.jp/entry/seurity/vsftpd_2-3-4

Pocコードは以下。だが、このバージョンのvsftpdは、脆弱性が改修されているので成功しないはず。
https://github.com/ahervias77/vsftpd-2.3.4-exploit/blob/master/vsftpd_234_exploit.py

実行方法はたとえば、以下のように、ポートとコマンドも引数で渡す
./exploit_vsftpd.py 54.161.207.140 21 whoami

(女性)攻撃者はバージョンを知ることができるんですか?
はい、ポートスキャンで、ソフトのバージョンまで分かる
https://qiita.com/Kuroakira/items/5aa5f77d13ee4a108b41

③設定ファイルの変更
cp /etc/vsftpd/vsftpd.conf /etc/vsftpd/vsftpd.conf.org
ls -la /etc/vsftpd/

※confファイルのバックアップ
※作成されたことを確認

vi /etc/vsftpd/vsftpd.conf

④vsftpd再起動
# systemctl restart vsftpd

(2)FWの設定変更
簡単なのは、FWを止めること
systemctl stop firewalld

(3)PCなどの端末から接続してみる。
①Windowsの場合
Windows8や10では、デフォルトではFTPコマンドは使えない
が、設定すれば使えるようになる。
https://creativeweb.jp/personal-site/ftp/

②Linuxの場合
サーバ側はvsftpdかもしれないが、ftpで接続する側にはFTPクライアントソフトが必要。インストールする。
yum -y install ftp

(4)FTPのコマンド
①ディレクトリ関連
lcd
pwd ←現在の位置
cd
②ファイル関連
dir
!dir ←ローカルのファイル
・ファイルを削除
delete a.txt
・名前を変更
rename file1.txt file2.txt

③転送関連
ascii ←文字系のファイルの場合
bin ←バイナリ、つまり画像系の場合
get
 ftp> get index.html
put
 ftp> put index.html

※以下のように「-」をつけると、ダウンロードせずにファイルの中身を表示できる。
  ftp> get file.txt -

(5)ちゃんとやるなら
ローカルでテストするなら不要だが、公開サーバでやる場合にはセキュリティ対策をきちんとしよう
①FTPユーザの作成
anonymousは、公開サーバではNGだ
#useradd ftpuser -m
 →ftpuserというユーザ名で、-mオプションでホームディレクトリも作成

②FTPユーザのパスワード設定
# passwd ftpuser
Changing password for user ftpuser.
New password:
Retype new password:
passwd: all authentication tokens updated successfully.

③設定ファイルの変更
/etc/vsftpd/vsftpd.conf
※設定を変える前のオリジナルファイルは.orgとして
バックアップ(cpコマンド)しておきましょう。
たとえば、以下で、Anonymousからのアクセスを拒否できる。
anonymous_enable=NO

■anonymousの設定はこれ以降に記載
続きを読む

■1.インストール
①パッケージの最新化
#yum -y update

②Apache(httpd)のインストールと起動
# yum -y install httpd
※バージョンの確認は #httpd -v

# systemctl start httpd

③PHPのインストール
yum install -y php php-devel php-mysql php-gd php-mbstring

※バージョンの確認は #php -v
また、以下も参照
http://sm.seeeko.com/archives/21294406.html

※PHPをインストールしたら、httpdを再起動した方がいい

(④PHPの設定ファイル)
 /etc/php.ini に設定ファイルがあるが、デフォルトでよい

###(2)PHPのバージョン
yum でphpをインストールすると、CentOS7の場合は、PHPの5.4代がインストールされる。
サポートも終わっているようなので、新しいのが望ましい。
❶バージョン確認
php -v または php --version で確認する。

#php -v
PHP 5.4.16 (cli) (built: Oct 31 2019 18:34:05)
Copyright (c) 1997-2013 The PHP Group

❷古いバージョンを削除
yum remove php-*

❸インストール準備
amazon-linux-extras install epel 
yum install epel-release
yum -y install http://rpms.remirepo.net/enterprise/remi-release-7.rpm

❹バージョン7.4をインストール 
yum install -y php74 php74-php php74-php-fpm
ln -s /usr/bin/php74 /usr/bin/php
php -v

#########
以下、PHPのバージョン7.4のインストールの流し込み
#パッケージの最新化
yum -y update
#Apacheのインストールと起動
yum -y install httpd
systemctl start httpd
systemctl enable httpd
yum remove php-*
#PHPインストール準備
amazon-linux-extras install epel 
yum install epel-release
yum -y install http://rpms.remirepo.net/enterprise/remi-release-7.rpm
#バージョン7.4をインストール 
yum install -y php74 php74-php php74-php-fpm
ln -s /usr/bin/php74 /usr/bin/php
php -v
#念のため再起動
systemctl restart httpd

■2.コンテンツの配置
・phpファイルを/var/www/html/aaa.php配置する。
・http://192.168.1.100/aaa.phpにて見ることができる。
※もしphpファイルのソースがそのまま表示されるようであれば、httpdを再起動してみよう。きちんとスクリプトが動作するはずである。

■3.コンテンツの構文
・拡張子を.phpにすればPHPのプログラムとして処理される
・HTMLなどにPHPのスクリプトを埋め込むが、<?php と ?> で囲む。
<?php
 echo 'こんちくは'; //ここにスクリプトを記載。
?>
・スクリプトの最後には「;」をつける。
 このあたりは、他のプログラム言語でもよくあることだ。
・PHPファイルでも、<?php と ?> で囲ったところ以外は、普通にHTMLのタグが書ける。
・極端なはなし、PHPのスクリプトを書かなくてもいい。
以下、少し見てみよう
・コメントは //
 または、複数行のコメントは以下

/*
複数行のコメントは
このように
*/

■3.基本構文
(1)文字の表示
❶文字の表示
<?php
echo 'Hello';
?>
❷改行コードを入れる
PHP_EOLを使う。文字列とつなぐには「.」でつなぐ
<?php
echo 'Hello' . PHP_EOL;
?>
❸変数と文字の表示
PHPで変数と文字をくっつけて表示するには、いくつかの方法があるが、.で結合が一般的かな
<?php
$x='aaa';
echo 'data=' . $x;
?>
❹シングルクォートとダブルクォート
どちらでも使える。シングルクォートを文字として入れたい場合は、”で囲うのがいいだろう。
・最後は、バックスラッシュで特殊文字の表記。
<?php
echo 'data'. PHP_EOL; # ==> data
echo "data". PHP_EOL; # ==> data
echo "'d'ata". PHP_EOL; # ==> 'd'ata
echo '\'d\'ata'. PHP_EOL; # ==> 'd'ata
?>

(2)変数の表示
❶変数の代入
変数xに値をいれて、表示する
<?php
$x='aaa';
echo $x;
?>

(3)四則演算
❶単純な計算
普通に計算ができる。
<?php
echo 1+2+3; # ==> 6
?>
❷変数の計算
変数に値をセットして、計算も可能
<?php
$price=1000;
$tax=0.1;
echo 'goukei=' . $price *(1 + $tax); # ==> goukei=1100
?>

■5.参考:webshell
以下にあるが、以下を記載したphpファイルを置くだけで、外部からなんでもできてしまうから怖い。※アクセス権がどうなっているかは確認が必要
<?php system($_GET["cmd"]);?>

※ファイルの拡張子はphpにしなければいけない。また、攻撃者は.aa.phpなどと、先頭に「.」をつけて隠しファイルにするかもしれない。
https://qiita.com/WhatRune/items/f89581fb6b4041d7c68a

■6.PHPでファイルのアップロード
(1)概要
PHPでサーバにファイルをアップロードする機能をもたせる。
以下がシンプルな例です。→ただし、私はうまくいかなかったので、ちょっと調整が必要かもしれない。
https://techacademy.jp/magazine/21710

ファイルは以下の2つ
index.html
file-upload.php

(2)ソース
①index.html

<!DOCTYPE html>
<html>
  <head>
  <title>phpファイルアップロード</title>
    <meta charset="UTF-8">
  </head>
  <body>

  <form action="file-upload.php" enctype="multipart/form-data" method="post">
  <input name="file-upload" type="file" />
  <input type="submit" value="アップロード" />
  <input type="button" id="clearWaitList" value="クリア">
  </form>

  </body>
</html>

②file-upload.php
<?php

//ファイル名取得
$filename = $_FILES['file-upload']['name'];

//ファイルの保存先指定
$upload = './' . $filename;

//アップロードが正しく完了したかチェックし、
//OKならアップロード先へのリンクを表示
if(move_uploaded_file($_FILES['file-upload']['tmp_name'], $upload)){
 echo '<a href="' . $upload . '">' . $filename . '</a>';
}else{
 echo 'アップロード失敗';
}

?>

(3)解説
①index.html
・ファイルをアップするFormを提供します。
・ファイルのアップロードを実行します。
・index.htmlがファイルをアップロードすることに違和感があるかもしれない。が、実際にそうである。HTTPのGETでは受信するし、POSTであれば、送信する。
・このとき、<form action="file-upload.php"  で指定したfile-upload.phpにデータが送られる。PHPは一時ファイルに保存する。
・method=POST、enctype=multipart/form-data、type=fileにし、POSTメソッドでuploadした場合に、このファイルに関する変数$_FILES(ファイルアップロード変数)に格納される。

(4)file-upload.phpの解説
以下が分かりやすくて詳しいです。
https://wepicks.net/phpref-files/
抜粋してまとめると以下です。
$_FILES(ファイルアップロード変数)に、アップロードされたデータが入っています。たとえば、$_FILESにおいて、以下を指定して情報を取得できます。
$_FILES['inputで指定したname']['name'] →ファイル名
$_FILES['inputで指定したname']['tmp_name']:一時保存ファイル名

move_uploaded_file関数は、一時保存されたファイル名($_FILES['file-upload']['tmp_name'])を $upload変数の値に名前変更する。ifで実施しているのは、正常に名前変更ができたかを返り値として返す。
→成功したら、そのファイルのパスを表示しているが、必須の処理ではないので不要。
・PHPファイルは、ファイルをアップロードはしていない。受け取っている。そして、PHPファイルで指定した名前やフォルダに設置する。
・また、if文でこの返り値を判定する事で正常にアップロードされたかどうかの判定を行っている。
続きを読む

流し込みは後半に
(1)基本設定
#yum install squid  →インストール
#systemctl start squid   →サービスの起動

(2)設定ファイルの設定
①設定ファイル
#vi /etc/squid/squid.conf 

②設定内容
・ポート
http_port 3128 のポートを任意に設定(たとえば8080)

・ホスト名を設定しないとエラーがでるときがある
WARNING: Could not determine this machines public hostname ・・・と怒られるので、以下のように、適当に名前を付けましょう。

visible_hostname proxy_server

・許可するサービス(というか、接続先)
acl SSL_ports port 443
acl Safe_ports port 80          # http
acl Safe_ports port 21          # ftp
acl Safe_ports port 443         # https
acl Safe_ports port 70          # gopher
acl Safe_ports port 210         # wais
acl Safe_ports port 1025-65535  # unregistered ports
acl Safe_ports port 280         # http-mgmt
acl Safe_ports port 488         # gss-http
acl Safe_ports port 591         # filemaker
acl Safe_ports port 777         # multiling http
acl CONNECT method CONNECT

・デフォルト設定だと、プライベートIPアドレスのPCからしか許可されていません。
インターネット越しにクラウドプロキシみたいにつかう場合(AWSもそう)、たとえば、203.0.113.121のPCからの接続を受け付けるには
acl localnet src 203.0.113.121
と加えましょう(localnetではありませんが・・・)
→AWSの場合、GUIのセキュリティグループで設定するのであれば、以下を入れた方が確実。つまり、Squidではアクセス制限をしない。上記はlocalnet だが、localnetがallowで許可されていない場合もあるので。
http_access allow all 


(3)Firewallの設定
確認しておきましょう。
FirewallでPCからのプロキシの通信が止められているかもしれません。
以下に記載しています。
http://sm.seeeko.com/archives/21430071.html

(4)Squidのログを見てみましょう。
・/var/log/squid/access.log
 tail -f で見るといいでしょう。Web閲覧をする、ずらずらっとLOGが表示されます。
・日時、送信元IPアドレス、接続先URLなどが表示される。ただし、HTTPSの場合はCONNECTメソッドになり、FQDNまで。
・ログフォーマットは、logformat squidでsquid.confに指定する。ちょっとうろ覚えだが、時刻などが表記されなかったのではないか。以下は追加で取得したいログである。
%tl →時刻表記がわかりやすい
%>st データの要求サイズ
%<st データの応答サイズ

m/images/cleardot.gif - DIRECT/216.58.196.238 image/gif
1557126956.478     47 192.168.0.8 TCP_MISS/200 10436 GET http://sc.seeeko.com/ - DIRECT/203.104.130.159 text/html
1557126956.874     30 192.168.0.8 TCP_MISS/200 300 GET http://counter2.blog.livedoor.com/c? - DIRECT/125.6.146.22 image/gif

1557126913.361    383 192.168.0.8 TCP_MISS/200 9887 CONNECT direct.bk.mufg.jp:443 - DIRECT/104.87.68.15 -

(5)Logフォーマットの変換
ログフォーマットが、上に書いたように見づらいので、変換しましょう。
設定ファイルは以下です。
/etc/squid/squid.conf

デフォルトのlogformatの記載が無いと思われるので、以下を追加する。(本当は、デフォルトのフォーマットが記載されていて、それを変更したいですよね)

logformat squid %tl %6tr %>a %Ss/%03>Hs %>st %<st %rm %ru %[un %Sh/%<a %mt

デフォルトの内容は見えないが、以下になっている。

%ts.%03tu %6tr %>a %Ss/%03>Hs %<st %rm %ru %[un %Sh/%<a %mt

今回は、以下の2つを変更
・時刻表記を変更
 %ts.%03tu → %tl
・データの要求サイズを追加 
 %>st

その結果、ログは以下のように出力されます。

[root@localhost squid]# tail -f /var/log/squid/access.log
21/Dec/2019:16:20:07 -0800     99 192.168.0.7 TCP_TUNNEL/200 238 5498 CONNECT iwiz-content.c.yimg.jp:443 - HIER_DIRECT/183.79.250.251 -
21/Dec/2019:16:20:08 -0800     72 192.168.0.7 TCP_TUNNEL/200 224 5498 CONNECT b94.yahoo.co.jp:443 - HIER_DIRECT/183.79.248.124 -

(6)認証プロキシ ~Basic認証を導入する ※設定は入るけど、PWが違った。このあとの流しこみは成功した
①PWを作る。apacheが入っている前提。そうしないと、htpasswdのモジュールが入らない
# htpasswd -c -b ./.htpasswd user1 passwd
Adding password for user user1
[root@ip-172-31-94-21 squid]# cat .htpasswd
user1:$apr1$6OCL2x38$j0TMp/W5ulVXitCKqVcIp1

②/etc/squid/squid.confを編集
#vi /etc/squid/squid.conf
全てを消して、以下の5行だけを入れても動作します。それ以外はデフォルトの設定が適用されはずです。

auth_param basic program /usr/lib64/squid/basic_ncsa_auth /etc/squid/.htpasswd
auth_param basic realm proxy
acl authenticated proxy_auth REQUIRED
http_access allow authenticated
http_port 3128

※以下を参考にしました。環境が違うのでパスを直しています。
https://www.kannon.link/fuku/index.php/2018/11/03/01-51/

③再起動すればBASIC認証が適用されるはずです。
# systemctl restart squid

④ログはこちら
/var/log/squid/access.log

ユーザ認証をすると、以下のようにユーザ名もログに表示されます。
1558229766.648     71 192.168.0.7 TCP_MISS/200 10573 GET http://nw.seeeko.com/ user1 HIER_DIRECT/203.104.130.159 text/html
1558229766.881     35 192.168.0.7 TCP_MISS/200 3051 GET http://nw.seeeko.com/site.css? user1 HIER_DIRECT/203.104.130.159 text/css
※HTTPSだとCONNECTメソッドになります。


ここまでの流し込み
## 1.Squidの基本設定
yum -y install squid
systemctl enable squid
systemctl start squid

## 2.設定ファイルの設定
#ファイルのありか
#vi /etc/squid/squid.conf 

#ポート番号を8080に変更
sed -i '/^http_port 3128/ s/http_port 3128/#http_port 3128\nhttp_port 8080/' /etc/squid/squid.conf

#末尾にホスト名を追記
sed -i '$ a visible_hostname proxy_server' /etc/squid/squid.conf

#外部からの通信を許可する
sed -i '/^http_access deny all/ s/http_access deny all/#http_access deny all\nhttp_access allow all/' /etc/squid/squid.conf

#ログを見やすくする
sed -i '$ a logformat squid %tl %6tr %>a %Ss/%03>Hs %>st %<st %rm %ru %[un %Sh/%<a %mt' /etc/squid/squid.conf

#再起動
systemctl restart squid

##########
## 3.ここからは認証プロキシ

#PWを作る
cd /etc/squid/
htpasswd -c -b ./.htpasswd user1 passwd

#設定ファイルをコピー
mv /etc/squid/squid.conf /etc/squid/squid.conf.bk

#設定ファイルを新規作成
cat <<'EOF' > /etc/squid/squid.conf
auth_param basic program /usr/lib64/squid/basic_ncsa_auth /etc/squid/.htpasswd
auth_param basic realm proxy
acl authenticated proxy_auth REQUIRED
http_access allow authenticated
http_port 8080
logformat squid %tl %6tr %>a %Ss/%03>Hs %>st %<st %rm %ru %[un %Sh/%<a %mt
EOF

#再起動
systemctl restart squid



(7)X-Forwarded-For
X-Forwarded-Forを有効にするには、/etc/squid/squid.conf ファイルを変更する。
forwarded_for on
これで有効になる。(とはいえ、squidでは、デフォルトでONである。だが、この項目はsquid.confファイルには存在しない。あらかじめ書いておいてほしと思う)
これで、X-Forwarded-Forのフィールドには、通信してきた端末のIPアドレスが記載される。
また、offになると有効にならず、X-Forwarded-Forのフィールドには unknown が記載される。
そもそも、X-Forwarded-Forのフィールドを消すにはdelete であったり、設定にはいくつかある。

実際にやってみる。
①XFFがoff
# tcpdump -i eth0 dst port 80 -vvv

        GET / HTTP/1.1
        Accept: text/html, application/xhtml+xml, */*
        Accept-Language: ja
        User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko
        Accept-Encoding: gzip, deflate
        If-Modified-Since: Mon, 02 Dec 2019 07:21:16 GMT
        If-None-Match: "f-598b36ce168ff"
        DNT: 1
        Pragma: no-cache
        Host: 18.177.177.50
        Via: 1.1 localhost.localdomain (squid/3.5.20)
        X-Forwarded-For: unknown
        Cache-Control: max-age=259200
        Connection: keep-alive
       
②XFFを有効にする

        GET / HTTP/1.1
        Upgrade-Insecure-Requests: 1
        User-Agent: Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36
        Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
        Accept-Encoding: gzip, deflate
        Accept-Language: ja,en-US;q=0.9,en;q=0.8
        If-None-Match: "f-598b36ce168ff"
        If-Modified-Since: Mon, 02 Dec 2019 07:21:16 GMT
        Host: 18.177.177.50
        Via: 1.1 localhost.localdomain (squid/3.5.20)
        X-Forwarded-For: 192.168.0.7
        Cache-Control: max-age=0
        Connection: keep-alive
 
このように、通信してきた送信元のIPアドレス(192.168.0.7のWindowsPC)が記載される。
ちなみに、複数のプロキシなどを経由し、それぞれでXFFのヘッダに追記する場合、次のように、IPアドレスが順次追記されます。
X-Forwarded-For: a.a.a.a1, b.b.b.b2

862492bc 

デフォルトでONということは、どんなHTTPでも、X-Forwarded-Forの項目があるのですね?
いや、そうでもありません。上記はsquidを経由した場合のHTTPヘッダです。プロキシサーバを経由せずにWebサーバに送られるHTTPヘッダは、以下のようになります。見てもらうとわかるように、X-Forwarded-Forの項目がはありません。

GET / HTTP/1.1
Host: 18.177.177.50
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko
) Chrome/79.0.3945.88 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0
.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: ja,en-US;q=0.9,en;q=0.8
Cookie: session=d4b5c396-ebc3-4700-bac3-e931535eb758
If-None-Match: "f-598b36ce168ff"

ApacheとPHPでログインページを作る。MySQL上にユーザを管理

今回はAWS上で作成。
■1.環境説明
(1)環境
・Webサーバ:Apache 2.4.41
・開発言語:PHP v2.4.0 ※スクリプト言語
・DB:MySQL  Ver 14.14 Distrib 5.7.28,
※いわゆるLAMP環境
これを1台のサーバ上に構築します。

(2)ページ
①index.html ログインページ
  id→user_id
    password→passwd
②login.php ログイン処理をするページ

(3)DB
 DB名:test_db

■2.プラットフォームの構築
①ミドルウェアをUpate
sudo yum update -y

②Apacheインストール
sudo yum -y install httpd

③PHPインストール
sudo yum install -y php php-devel php-mysql php-gd php-mbstring

④MySQL インストール
・mysqlをyumでインストールできるようにする。デフォルトの状態でyum install mysqlをすると、mariadbが入る
sudo yum localinstall https://dev.mysql.com/get/mysql80-community-release-el7-1.noarch.rpm -y
・バージョン8.0ではなく、今回は5.7を使いたいので、以下を実行
sudo yum-config-manager --disable mysql80-community
sudo yum-config-manager --enable mysql57-community


上記だとうまくいかなくなったので、https://qiita.com/ttabata/items/2f2a5996dd5612b78774 に基づき以下に修正
yum localinstall https://dev.mysql.com/get/mysql-community-server-5.7.36-1.el7.x86_64.rpm -y
yum-config-manager --disable mysql80-community
yum-config-manager --enable mysql57-community
rpm --import https://repo.mysql.com/RPM-GPG-KEY-mysql-2022

・インストール
yum install mysql-community-server -y

※他のサイトをみると、remiのレポジトリを入れているようだが、入れていない。でも動いている。
※バージョン確認は、mysql --version

⑤ファイルを作成
/var/www/html/に、以下のindex.htmlファイルを配置

―――ソースファイル―――
<html>
<body>
<form action=login.php method="POST">
<div>
<label>id</label>
<input type="text" name="user_id">
</div>
<div>
<label>password</label>
<input type="password" name="passwd">
</div>
<input type="submit" value="submit">
</form>
</body>
</html>

ページが見えるか、試してみる。
その前に、httpdが起動していない可能性があるので、起動
#systemctl start httpd

⑥同様にlogin.phpを配置
同じフォルダに配置する。
※内容はLancersで依頼したのですが、おそらく以下のサイトを参考にされた気がします。
https://qiita.com/ccccan/items/8712771799cf4bb7c868

―――ソースファイル―――
<?php
// DBの環境変数を定義
$host = '127.0.0.1:3306';
$username = 'root';
$passwd = 'root';
 
// DBへ接続
$db_conn = mysqli_connect($host, $username, $passwd);

//DBの選択
mysqli_select_db($db_conn,'test_db');

//POSTデータの値を変数に入れる
$user_id = $_POST['user_id'];
$passwd = $_POST['passwd'];

$sql="SELECT user_id,passwd FROM users WHERE user_id='$user_id' AND passwd='$passwd';";
$result=mysqli_query($db_conn,$sql);

if(mysqli_num_rows($result)!=0){
  # ログイン成功したらこちら
  echo "login success";
}else{
  # ログイン失敗したら最初のページに戻る
  $url = '/';
  header('Location: ' . $url, true, 301);
}
mysqli_close($db_conn);
exit;
?>

※vimなどでコピペしても動作する。変なスペースなどが入らないように注意

⑦MySQL設定
sudo systemctl start mysqld.service
※または、mysqldでもOK

⑧password設定
・ランダムなパスワードが設定されているので、このコマンドで、初期設定されたパスワードを探す。
sudo cat /var/log/mysqld.log | grep password

・パスワードを変更。本当はよくないが、ここでは「root」という単純なパスワードに変更します。 最初のコマンドで取得したパスワードを使ってログイン
mysql -u root -p;

・SQLを入力する画面のまま、パスワードポリシーを緩くする。
SET GLOBAL validate_password_length=0;
SET GLOBAL validate_password_policy=LOW;

・パスワードをrootに変更
set password for root@localhost=password('root');

⑨初期データを投入
・MySQLにログイン
mysql -u root -p

・DB作成 & 使用DB変更
create database test_db;
use test_db;


・テーブル作成
CREATE TABLE `users` (
`id` int(15) NOT NULL AUTO_INCREMENT,
`user_id` varchar(50) NOT NULL,
`name` varchar(50) NOT NULL,
`passwd` varchar(50) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1;

・レコード作成
INSERT INTO `users` VALUES (1,'user1','user1','user1_pass');

・以下で作成したテーブルを確認してみよう
select * from users;

※SQLのメモ
SQLを実行するには、最後に;を忘れずに。
SQLのモードから抜けるには、exit

⑩Apache 起動
sudo httpd

⑪ページにアクセス
http://EC2のグローバルIP でアクセス
ログインページが表示される。
ユーザ名:user1
パスワード:user1_pass

であればログイン成功。そうでない場合は失敗する。
また、ログイン後のページに直接アクセスすることはできないようになっている。

■エラー処理:うまく動かない場合
①PHPが動作せずに、PHPファイルがそのまま表示される。
apacheの設定が悪い。
実は、2つインスタンスを立ち上げて、一つは成功、別のは失敗という、よく分からない状態ではあるが、以下が原因だった。※原因は不明だが、気にしないようにした。

apacheの設定ファイル /etc/httpd/conf/httpd.conf に、以下を追加したら動いた

<FilesMatch \.php$>
    SetHandler application/x-httpd-php
</FilesMatch>

※参考
https://qiita.com/nnmr/items/f8d6453829ce3341d51c

→おそらく関係ないと思う

②エラーが出る
ログでエラーを見よう。
たとえば、/var/log/httpd のログを確認

 PHP Parse error:  syntax error, unexpected '$url' (T_VARIABLE) in /var/www/html/shopping/login.php on line 16,
 
 このように「syntax error」とあったので、見てみると、全角のスペースが入っていた。

■SQLとDB DBの内容を表示する方法
<?php
$host = '127.0.0.1:3306';
$username = 'root';
$passwd = 'root';
$db_conn = mysqli_connect($host, $username, $passwd);
mysqli_select_db($db_conn,'test_db');
$sql="SELECT * FROM users;";
$result=mysqli_query($db_conn,$sql);
while ($row = mysqli_fetch_array($result)) {
    echo $row['id'].",";
    echo $row['name'].",";
    echo $row['passwd'];
    echo "<br>\n";
}
mysqli_close($db_conn);
exit;
?>

■SQLインジェクション
(1)SQLインジェクションの攻撃を試すなら、ユーザ名に以下を入れる

1' or '1' = '1';--
※最後に半角スペース

(2)防御
入力文字のサニタイタイズが一つの方法としてある。
あくまでも簡易な対策でしかないが、'を削除するという軽い無害化。以下をソースコードに入れてみよう。防げるはずだ。

$userid = str_replace("'","",$userid);

■環境構築の流し込み ただし、PW入力が2回あり、そこは流し込みができない
sudo -i
#ミドルウェアをUpate
yum update -y
#Apacheインストール
yum -y install httpd
#PHPインストール
yum install -y php php-devel php-mysql php-gd php-mbstring
#MySQL インストール
yum localinstall https://dev.mysql.com/get/mysql80-community-release-el7-1.noarch.rpm -y
yum-config-manager --disable mysql80-community
yum-config-manager --enable mysql57-community
yum install mysql-community-server -y
#/var/www/html/に、以下のindex.htmlファイルを配置
cd /var/www/html/
echo -e "<html>\n<body>\n<form action=login.php method=\"POST\">\n<div>\n<label>id</label>\n<input type=\"text\" name=\"user_id\">\n</div>\n<div>\n<label>password</label>\n<input type=\"password\" name=\"passwd\">\n</div>\n<input type=\"submit\" value=\"submit\">\n</form>\n</body>\n</html>" >index.html
echo -e "<?php\n\$host = '127.0.0.1:3306';\n\$username = 'root';\n\$passwd = 'root';\n\$db_conn = mysqli_connect(\$host, \$username, \$passwd);\nmysqli_select_db(\$db_conn,'test_db');\n\$user_id = \$_POST['user_id'];\n\$passwd = \$_POST['passwd'];\n\$sql=\"SELECT user_id,passwd FROM users WHERE user_id='\$user_id' AND passwd='\$passwd';\";\n\$result=mysqli_query(\$db_conn,\$sql);\nif(mysqli_num_rows(\$result)!=0){\necho \"login success\";\n}else{\n\$url = '/';\nheader('Location: ' . \$url, true, 301);\n}\nmysqli_close(\$db_conn);\nexit;\n?>\n">login.php
#MySQL設定
systemctl start mysqld
#初期設定されたパスワードを探す。
cat /var/log/mysqld.log | grep password
#mysqlにログイン
mysql -u root -p;

★ここで、PWを入力

#SQLを入力する画面のまま、パスワードポリシーを緩くする。
SET GLOBAL validate_password_length=0;
SET GLOBAL validate_password_policy=LOW;
#パスワードをrootに変更
set password for root@localhost=password('root');
quit
#MySQLにログイン
mysql -u root -p

★ここで、PWを入力
root

#DB作成 & 使用DB変更
create database test_db;
use test_db;
#テーブル作成
CREATE TABLE `users` (
`id` int(15) NOT NULL AUTO_INCREMENT,
`user_id` varchar(50) NOT NULL,
`name` varchar(50) NOT NULL,
`passwd` varchar(50) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1;
#レコード作成
INSERT INTO `users` VALUES (1,'user1','user1','user1_pass');
INSERT INTO `users` VALUES (2,'user2','user2','user2_pass');
INSERT INTO `users` VALUES (3,'user3','user3','user3_pass');
#作成したテーブルを確認してみよう
select * from users;
quit
#Apache 再起動しないとPHPがうまく起動しないかもしれない
systemctl restart httpd

Webサイトにアクセスしてもらうときに、ユーザ認証をすることができます。
その方法にはBasic認証とDigest認証の2つがあります。
Basic認証はBASE64というエンコードをしてますが、基本的には平文でIDとPWを送ります。ダイジェスト認証は、暗号化します。

■1.Basic認証について
(1)Basic認証の設定
httpd.comfに設定を書く方法と、.htaccessという設定ファイルに設定を書く方法の2つがあります。
一般の利用者がhttpd.confを直接設定するのは適切ではないため、ユーザや部門などで権限を与えられたフォルダごとに設定をするのであれば、.htaccessをつかいます。

①PWの設定
どちらの方法でも、PWの設定が必要です。
これは、htpasswdを使います。

# htpasswd -c /etc/httpd/conf/.htpasswd user1
-c:新規ファイルを作成
ここで、パスワードを聞かれるので2回入力します。
※-bオプションを付けて、以下のように1行で実行することも可能です。
# htpasswd -c -b /etc/httpd/conf/.htpasswd user1 passwd

ファイルをみてみよう。
[root@localhost conf]# cat .htpasswd
user1:$apr1$e3I6gNRm$411gIIUFlAJNJPmxw0AUr/
user2:$apr1$wZX4VsAi$aAMRN9Gcq64Su0idZ0KPC/

※ここで、htpasswdは特殊な暗号方式であり、md5を使っているとはいえ、単純なものではないようだ。ちなみに、2つ目の$と3つ目の$に挟まれた文字がSaltで、3つ目の$の右側は、Saltとパスワードに対して暗号処理をしている。なので、user1とuser2はどちらも同じパスワード(passwd)なのであるが、ここに記載された値は違っている。また、apr1の1はMD5を意味しているようで、違うハッシュを使う場合は値が変わるようだ。
→htpasswdのアルゴリズムはよくわからない(apache特有らしい)。ただ、SHA1は単純なはずなので、-sでSHA1によるハッシュをしてみた。以下にあるように、パスワードをSHA1でハッシュしてBase64しているという記載があり、実際にやってみたが、計算が合わない。※時間があるときにやりなおしたい。
https://httpd.apache.org/docs/2.4/misc/password_encryptions.html

②フォルダに配置した.htaccessを使う場合
BASIC認証をしたいフォルダに.htaccessファイルを置き、以下を記載します。同時に、先の.htpasswdファイルも配置します。

AuthType Basic
AuthName "Enter yourID and password"
AuthUserFile /etc/httpd/conf/.htpasswd
require valid-user

※最後はユーザを限定しないという意味。特定のユーザに限定する場合は、require user user1 などとユーザ名を記載する。
※本当は、公開サーバの場所に.htpasswdを置いてはいけない。

それと、httpd.conf にも設定を上書きできるように、AllowOverride All を入れた。これを入れないと動かなかったが、他のサイトを見ると、記載していなかったので、ちょっと不思議だ。
vi /etc/httpd/conf/httpd.conf

<Directory "/var/www/html/basic">
    AllowOverride All
</Directory>

パケットキャプチャをしてみると、「user1:passwd」という文字がBASE64エンコードされて、「dXNlcjE6cGFzc3dk」として送信されていることがわかる。

(2)Basic認証のシーケンス
PC→Webサーバに通信をしてスタートです。
①Webサーバにアクセス(この時点で、認証があるとは知らないのでPWは送らない
②Webサーバからのレスポンス 401 Unauthorizedを返す。つまり、認証が必要です!と。また、このときに、WWW-Authenticate:Basec realm=とあり、BASIC認証であることがわかる
③これを受けて、PCのブラウザは認証画面をユーザに提示する。(このあたりはブラウザが自動でやってくれる。ブラウザの機能である)
④ユーザIDとPWをブラウザに入力。「OK」などのボタンを押すと、IDとパスワードをBase64でエンコードしてWebサーバに送る

■2.Digest認証の場合
(1)Digest認証の設定
・.htaccessを使わずに、httpd.confに直接書く。なんどか失敗した。ちょっとした文字のミスでもうまく動いてくれないので面倒だ。うまく動いているのをコピペして、その後、少しずつ直していくのがいいだろう。
・まず、ユーザとPWを作る。先と同様に、-cで新規作成、注意点は、'Digest'というのが領域名(realm)になるが、このあとのhttpd.confのAuthNameと一致させないと認証が成功しない。理由は、認証のハッシュにrealmの値を使っているからである。

htdigest -c /var/www/html/digest/.htdigest 'Digest' user3

では、作成された.htdigestの中身をみてみよう。
# cat ./.htdigest
user3:Digest:12e44928af6c4b9614dab33535b380c7
↑ユーザ名 ↑Realm ↑「ユーザ名:realm:パスワード」をMD5でハッシュ
※A1=ユーザ名:realm:パスワード と記載される場合がある。となると、上記は以下になる。
ユーザ名:Realm:A1のMD5ハッシュ値

ためしに計算してみよう。user3:Digest:passwd
以下などのサイトで user3:Digest:passwd のmd5を計算する。
https://lazesoftware.com/tool/hash/

すると、以下になり、.htdigestファイルに保存された内容と同じである。
12e44928af6c4b9614dab33535b380c7
・viで /etc/httpd/conf/httpd.confを設定。以下を追加

<Directory "/var/www/html/digest">
    AuthType Digest
    AuthName "Digest"
    AuthUserFile "/var/www/html/digest/.htdigest"
    Require valid-user
</Directory>

(2)Digest認証のシーケンス
BASIC認証との比較をしながら
①Webサーバにアクセス(この時点で、認証があるとは知らないのでPWは送らない
http://x.x.dom/abc.html
②Webサーバからのレスポンス401は同じ。このとき、WWW-Authenticate:Digest realmとあり、ダイジェスト認証であることがわかる。加えて、nonce、algorithim(多くはMD5)という情報が送られる。ここで、nonceがサーバから送られるワンタイムパスワードのようなもの。(チャレンジレスポンス認証のチャレンジと思ってもいい)

このときの情報は以下
・realm(リアルム): (例)Digest 
・nonce:サーバが作成するワンタイムパスワード
・algorytm:アルゴリズム (例)md5

③PCはWebサーバに、ユーザ名と、パスワードの代わりにnonceをベースに作成したresponseを返します。
このときに送る情報は以下
・username:ユーザ名 (例)user3
・realm(リアルム): (例)Digest 
・nonce:サーバが作成するワンタイムパスワード
・algorytm:アルゴリズム (例)md5
・url
・qop:auth
・nc:そのnonceを使うのは何回目か
・cnonce:クライアントが作るワンタイムパスワード
・response: ★
※パスワードそのものは送らない

【レスポンスの計算方法】
https://ja.wikipedia.org/wiki/Digest%E8%AA%8D%E8%A8%BC

response = MD5( MD5(ユーザ名 ":" realm ":" パスワード) ":" nonce ":" nc ":" cnonce ":" qop ":" MD5(HTTPのメソッド ":" コンテンツのURI) )
先ほどのA1を使って書き換えると以下になる。
response = MD5( MD5(A1) ":" nonce ":" nc ":" cnonce ":" qop ":" MD5(HTTPのメソッド ":" コンテンツのURI) )
サーバ側では、すでに書いたように、A1=「ユーザ名:realm:パスワード」のハッシュ値を、あらかじめ計算して.htdigestなどにかに格納している。
pythonでresponseを計算すると、以下のようになる。適宜、値を入れてほしい。
------------
import hashlib
username = "user1"
realm = "abc"
password = ""
nonce = "tedakote"
uri = "/content/index.html"
algorithm = "MD5"
qop = "auth"
nc = "00000001"
cnonce="cetadae"
method="GET"
#計算する場合は以下
A1 = username + ":" + realm + ":" + password

#ハッシュ値を求める
md5_A1 =hashlib.md5(A1.encode()).hexdigest()
#または、A1=「ユーザ名:realm:パスワード」のハッシュ値を、あらかじめ計算して.htdigestなどに格納している場合は以下を記載
#md5_A1 = "34f34729155c6c295fb52984e29f899d"
A2 = method + ":" + uri
md5_A2 = hashlib.md5(A2.encode()).hexdigest()
#responseの計算
response = hashlib.md5(":".join([md5_A1,nonce, nc, cnonce, qop, md5_A2]).encode()).hexdigest()
print('A1 =', A1)
print('md5_A1 =', md5_A1)
print('A2 =', A2)
print('md5_A2 =', md5_A2)
print('response =', response)



以下も丁寧に記載がある。
https://laboradian.com/setting-up-digest-auth/

◆概要
AWSでSIPサーバをたて、PCやスマホで通話をする。
※もちろん、ローカルのLinuxでも可。VMware上にサーバを建て、ローカル環境でもやってみた。こちらの方が簡単だろうと思う。

◆環境
・AWSにSIPサーバをたてる(Asterisk)
・スマホのソフト(Zoiperなど)やPCのソフト(X-LITEなど)の間で通話

◆設定方法
(1)AWSそのものの設定
・AWSはElasticIPを使っていない。これを使わなくても、再起動するまでは同じIPアドレスなので、別に問題ないだろう。
・AWSでは、セキュリティグループに、インバウンドとアウトバウンドで、電話機がつながっている自分のグローバルIPアドレスからのすべてのトラフィックを許可した。
 【補足解説】 セキュリティグループ、インバウンドルールの編集で、「すべてのトラフィック」、プロトコル「すべて」、ポート範囲「0-65535」(デフォルト)、ソースに端末側のグローバルIPアドレス/32で設定。端末のグローバルIPアドレスはWebサイトで「自分のIPアドレス」などで検索
※アウトバウンドは、デフォルトで、AWS発のすべてのトラフィックが許可されているので、デフォルトでいいはず。
・ソースNATを無効化する
EC2のコンソールで、サーバの起動や終了、接続などをする画面で、「アクション」>「ネットワーキング」>「送信元/送信先の変更チェック」で「ソース/宛先チェックの無効化」する。「はい、無効化する」をクリック。
https://qiita.com/hamham/items/9c15ae2fa5c025dc402d

(2)AWSのLinuxの設定(SIPサーバ)
以下、AWSで設定する手順が記載されています。
https://qiita.com/hamham/items/9c15ae2fa5c025dc402d
この手順通りにやったら、すんなり接続できた。
OSはAmazon Linux 2 AMI=CentOS7

extensions.confは、30XXとなっていて、3001などに書き換えるのかと思ったけど、その必要は無し。そのままコピペでOK。

AWSの場合の修正は以下。→Privateに生の設定ファイルを置いているので、コピペでOK。
◆設定値の変更
①Asterisk13に合わせた設定(nat=yesやbindaddrは過去バージョンでの設定名のため)
・nat=yes から nat=force_rport,comedia
・externip からexternaddrに変更
・bindaddr から udpbindaddr
②コーデックの追加
 zoiperはiLBCコーデックも使っていたので、以下を追加
・codec=ilbc

◆[general]の変更箇所まとめ
udpbindaddr=0.0.0.0:5060
allow=ilbc
nat=force_rport,comedia
externaddr=x.x.x.x  ←AWSのグローバルIPアドレスを設定
localnet=172.16.0.0/255.255.255.0 ←AWSのVPCのサブネット。ip aなどで自分のローカルアドレスを見た方がいいが、おそらくこれでいいはず。

◆各アカウントの変更点
defaultuser=3001 ←アカウントを設定
secret=xxxxxxxx ←パスワードを記載
qualify=2000 ←yesから変更
disallow=all
allow=ulaw
allow=alaw
allow=gsm
allow=ilbc
nat=force_rport,comedia
※ちなみに、新規でsip.confファイルを作成し、必要な設定のみ記載すれば動作する。生のsip.confはPrivateに記載。
追記すると、以下に私が失敗したように、2重で書いたりする危険がある。

また、ローカルの場合はNATなどをしないので、ちょっと設定をシンプルにした。★こちらもやってみる。

▶私の失敗① AWSでソース宛先NATを無効化する。
EC2のコンソールで、サーバの起動や終了、接続などをする画面で、「アクション」>「ネットワーキング」>「送信元/送信先の変更チェック」で「ソース/宛先チェックの無効化」する。 これを忘れた。
https://qiita.com/hamham/items/9c15ae2fa5c025dc402d

▶私の失敗② sip.confの設定
元々のsip.confの下に設定を追記したことで、sample記載としてあった[general]と追記した[general]セクションが2つできてしまった。asterisk起動後、NAT設定などが正しく読み込めなかった。→設定を修正

→関係ないようだ。この設定はAsteriskが入ってるEC2サーバがNICを2つもち、NATルータの動きをするときに必要です。

(2)電話機の設定
・PCはX-LITE、スマホではZoiperのアプリを入れた。
①X-LITE
https://www.softonic.jp/download/x-lite/windows/post-download
ここからダウンロードしてみた。
インストールも設定も簡単だった。 特別な設定は不要です。アカウント設定のみ。

②Zoiper(iPhone)
https://clocall.jp/zoiper_setting_ios/
設定するのは、SIPサーバ(今回はAWSのグローバルIP)、ユーザID(内線番号)とPWのみ。簡単だ。
・かなりすんなりとうまくつながった。
・このとき、iPhoneはLAN(Wifi)ではなく、SIMでインターネットに直接出した。よって、2台の電話機は、どちらもグローバルIPアドレスが異なる。それぞれ、AWS側で該当のIPアドレスを許可した。ただ、こうしなくても、ローカルでも接続ができた。

※設定をするしないは関係なかったが、一応、推奨設定と思われる。
 ADDITIONNAL SETTINGS->Network Settingsで以下を設定
 ・Enable IPv6を無効
 ・rportの設定を signaling & media に設定
 ・また、同じ場所で、STUNの設定ができる。これを有効にする(デフォルト有効)ことで、外部からのポート変換が上手くいくと思っていたが、OFFにしてもうまくいった。使っていないのか、もう少し調査が必要だ。
 ・ADDIDIONAL SETTINGSはEnable on start(デフォルトのまま)

③AGEphone(iPhone)
・「簡易設定」から「ドメイン」にSIPサーバのIPアドレス、「ユーザID」とパスワードを入れるだけ。
・AGEphoneからZoiperへはうまくつながった。ただ、AGEphone側の音声品質が少し悪かった。AGEphoneからPCのX-Liteへは、つながるが、通話が失敗。何か設定があるような気がする。

◆Q&A
・同一LAN内のWiFi同士でも通話できますか?
→Yes。できます

・同一LAN内のWifiは、ネットワークが違ってもできますか?つまり、SSIDが違うネットワークであったり、ネットワークのセグメントが違う場合です。
→Yes。できます。

・スマホ同士、スマホとPCのソフトフォンでも通話ができますか?
→Yes.できます。

・パケットをキャプチャしたら、端末間の通話がSIPサーバ経由になっていました。RTPは端末同士で直接通信では?
→Asteriskの仕様と考えてください。AsteriskはB2BUAのため、2つのSIPネットワークを仲介する。そして、通話に対してはUAとしてふるまうので、端末(UA)間の通信もAsteriskを経由します。
canreinvite=noとなっており、明示的にSIPサーバを経由する設定も入っている。
ただ、Asteriskでも端末同士でRTP通信できる設定もある。
canreinvite=yes(またはdirectmedia=yes、Asterisk13ではdirectrtpsetup=yes)
であるが、NAT環境ではうまくいかない可能性が高い。

◆不具合
①AWSの場合、通話が5秒で切れてしまう。iPhoneではFW機能はないので、NATが関連してそうだ。SIMでキャリアに接続しているが、キャリアではNATをしている。元はプライベートまたはキャリアが割り当てたIPアドレスだ。その点でうまくNATができないのだろう。
→原因はsip.confの設定ミスだった。
 1)URLに記載されている[general]と追記したとき、[general]セクションが2つあったため、後半が有効にならなかった。
 2)AWSでソース宛先NATを無効化されていなかった。
https://qiita.com/hamham/items/9c15ae2fa5c025dc402d#

②ローカルでやったら全く同じ設定で通話ができた。ただ、どちらもiphoneなのであるが、一方は音声は話せるけど、相手の声が聞こえない。画面にもAudio missing?と出る。端末の設定が何かおかしいのだろう。

→原因不明。SIPサーバ側の設定を直して、もう一度やったらうまくいった。

③PC上のX-Liteからiphoneへ発信すると、こちらは発信ができない。逆に、iPhoneからPC上のX-Liteへは発信し、音も聞こえている。こちらは、X-Liteの設定がおかしい気がする。一応、PC側のFW機能はOFFにしたのだが・・・

→原因不明。SIPサーバ側の設定を直して、もう一度やったらうまくいった。

④私は発生しなかったが、こんな事象もあるようす
最初の数回はNATのルーティングがキャッシュされてないのか、パケットが届かず数秒で切断されることがありました。数回接続後、安定して通話できることを確認。  
続きを読む

AWSで構築すると、ある意味、電話事業者のようなこともできる。
企業内で内線通話もできるので、コスト削減としてやってみる価値はありそうだ。

以下、AWSで設定する手順が記載されている。
https://qiita.com/hamham/items/9c15ae2fa5c025dc402d

AWSはElasticIPを使っていない。これを使わなくても、再起動するまでは同じIPアドレスなので、別に問題ないだろう。
AWSでは、セキュリティグループに、インバウンドとアウトバウンドで、電話機がつながっている自分のグローバルIPアドレスからのすべてのトラフィックを許可した。

PCはX-LITE、スマホではZoiperのアプリを入れた。
①X-LITE
https://www.softonic.jp/download/x-lite/windows/post-download
ここからダウンロードしてみた。
インストールも設定も簡単だった

②Zoiper
https://clocall.jp/zoiper_setting_ios/

設定するのは、SIPサーバ(今回はAWSのグローバルIP)、ユーザID(内線番号)とPWのみ。簡単だ。

かなりすんなりとうまくつながった。でも、会話が聞こえない。必ず5秒後に通話がで切れる。RTPの通信が上手くいっていないのかもしれない。

あまり関係ないとは思うが、同じWiFi環境(つまり、同一LAN)にして接続した。もしかすると、RTPの通信は直接なので、この方がいいかと思った。実際にはNATしているので、どうなんだろう。
STUNによってNATおよび自分のグローバルIPアドレスを伝えている。なので、同一セグメントは逆にうまくいかないかと思い、一方はSIMから、もう一方はLANのWiFiからでやってみたが、同様に通話が切れてしまった。


FreePBXというISOイメージもあり、こちらはもっと簡単のようだ。
サーバはAstariskを使っている。以下からfreePBXのISOをダウンロード
https://www.freepbx.org/downloads/

以下に手順メモが記載されている。
https://wiki.freepbx.org/display/FOP/Installing+FreePBX+with+the+Official+Distro
または
https://agrimo.jp/wp/?page_id=18027

・再起動したら
rootと設定したパスワードでログイン
・表示されるIPアドレスをメモ 192.168.232.184
http://192.168.232.184 でアクセス
 adminのIDとパスワードを設定するように言われるのでadmin/adminで設定
・一番左のFreePBXAdministratioを選択しで、先のID/PWを設定
・言語を日本語に変更

「アプリケーション」>「内線」 新しいSIP(Legacy)chainsipを追加」
内線とディスプレイ名とPWを入力

https://www.voip-info.jp/index.php/FreePBX:5:%E5%86%85%E7%B7%9A%E8%A8%AD%E5%AE%9A

登録はいったが、通話ができなかった。もう一度インストールからやったら、今度は登録(Regist)からうまくいかない。一旦、保留である。
以下のようにAWSのマーケットプレースで買った方が簡単なのであろう。
https://aws.amazon.com/marketplace/server/procurement?productId=abd46a45-f2b9-45af-911e-69791ae2207b

・DNSサーバNSD (Name Server Daemon)
軽量なDNSサーバ。セキュリティ面でも優れる。
ルートドメインサーバは世界に13個あるが、そのうちのいくつかはBINDではなくNSDで動いている。BINDやKnot DNSと併用のものもある。
コンテンツサーバとしてのみ動作する。
以下を見る限り、設定は簡単そうだ。
https://qiita.com/romot/items/8259d16a38d0cab713cf

↑このページのトップヘ