Armadilloフォーラム

armadillo460 メールが送信できない

mukai

2014年2月18日 19時31分

いつもお世話になります。
向井と申します。

armadillo460にてメールの送信機能を実装しようとしています。

一応PCのUbuntu上では作成したプログラムでメール送信の動作が確認できてたのですが、
armadillo460上で同じプログラムを実行すると、SMTPサーバに接続するconnct()でエラーが
起こってしまいうまく接続していくれません。
gethostbyname( "SMTPドメイン名" )や、
socket(PF_INET, SOCK_STREAM, 0)
は正常に動作しているようです。

h_errnoをみると[EPERM=Operation not permitted]が発生しているようです。
MANを見てみても今一解決策が判りませんでした。

どなたか原因がわかる方いらっしゃいましたら教えていただけませんでしょうか。

コメント

nozawa-katuhiro

2014年2月18日 20時05分

こんにちは、野沢と申します。
> armadillo460にてメールの送信機能を実装しようとしています。
>
> 一応PCのUbuntu上では作成したプログラムでメール送信の動作が確認できてたのですが、
> armadillo460上で同じプログラムを実行すると、SMTPサーバに接続するconnct()でエラーが
> 起こってしまいうまく接続していくれません。
> gethostbyname( "SMTPドメイン名" )や、
> socket(PF_INET, SOCK_STREAM, 0)
> は正常に動作しているようです。
>
> h_errnoをみると[EPERM=Operation not permitted]が発生しているようです。
> MANを見てみても今一解決策が判りませんでした。

私もハマったんで、覚えてます。

単純にiptablesの設定です。

セキュリティーのために1024以下のポートは制限がついてます。

ACCEPT tcp -- anywhere anywhere tcp dpt:http
ACCEPT tcp -- anywhere anywhere tcp dpt:telnet
ACCEPT tcp -- anywhere anywhere tcp dpt:ftp
ACCEPT tcp -- anywhere anywhere tcp dpt:snmp
ACCEPT tcp -- anywhere anywhere tcp dpt:ssh
ACCEPT tcp -- anywhere anywhere tcp dpt:ftp-data

これ以外ははねられます。

こちらの設定は /etc/init.d/firewall で設定しています。

また、この起動時のスクリプトとして登録されており、
/etc/firewall.conf を編集することで、代表的なポートの許可ができます。

しかし、標準ではSMTPは入ってないようです。

/etc/init.d/firewall を編集してSMTPのポートを有効にすると良いでしょう。

と言っておきながら、Flashでユーザーランドを書き換えないとできないので
面倒ですよね。

そんな時は、/etc/config/rc.local の中に無理やりポートをあけるの仕組むといいかも。
書き換え後、Flash にセーブするのをお忘れなく。

また iptablesの使い方はWEBで自分で調べてくださればよいかと。

iptables -A INPUT -i eth0 -p tcp -d 0/0 --dport smtp -j ACCEPT
とか
iptables -A INPUT -i eth0 -p tcp -d 0/0 --dport smtps -j ACCEPT
とかかな?

メールのポートが違う場合は適当に直す必要がありますので、ご注意を。

これも面倒なら、iptables自体を無効にすることも可能ですが、おすすめできません。

では、良いアルマジロライフを。
通りすがりのLinux好きより(@の人じゃないですからね。)

中村です。

> iptables -A INPUT -i eth0 -p tcp -d 0/0 --dport smtp -j ACCEPT
> とか
> iptables -A INPUT -i eth0 -p tcp -d 0/0 --dport smtps -j ACCEPT
> とかかな?

INPUTじゃなくてOUTPUTですよ。

SMTPで出ていけるようにするには、
iptables -A OUTPUT -i eth0 -p tcp -d 0/0 --dport smtp -j ACCEPT
とする必要があります。

今Armadilloを動かせるものが手元にないのでatmark-distの
ソース(makeした後のromfs/etcの下)を見て、以下を書いてます。

> セキュリティーのために1024以下のポートは制限がついてます。
>
> ACCEPT tcp -- anywhere anywhere tcp dpt:http
> ACCEPT tcp -- anywhere anywhere tcp dpt:telnet
> ACCEPT tcp -- anywhere anywhere tcp dpt:ftp
> ACCEPT tcp -- anywhere anywhere tcp dpt:snmp
> ACCEPT tcp -- anywhere anywhere tcp dpt:ssh
> ACCEPT tcp -- anywhere anywhere tcp dpt:ftp-data
>
> これ以外ははねられます。

これらはすべてINPUTフィルタです。

質問はArmadilloから外部のSMTPサーバへの接続問題ですよね?
つまりOUTPUTフィルタの問題です。

> こちらの設定は /etc/init.d/firewall で設定しています。

このスクリプトをよく見てください。
次のようになってます。

# default setting: deny everything
iptables -F INPUT
iptables -P INPUT DROP
iptables -F OUTPUT
iptables -P OUTPUT DROP

# allow all non-external interfaces for everything
iptables -A INPUT -i ! $EXT -j ACCEPT
iptables -A OUTPUT -o ! $EXT -j ACCEPT

ここで$EXTは"eth0"です。

ここまでのルールで、eth0以外はINPUTもOUTPUTも全て許可ですが、
(余談ですが、eth0以外は入出力全て許可でいいのか?私は疑問です)
eth0はデフォルトでINPUTもOUTPUTも全て非許可(DROP)です。
でもって、たとえば、
if [ "$ALLOW_HTTP" = "yes" ]; then
iptables -A INPUT -i $EXT -p tcp -d 0/0 --dport http -j ACCEPT
fi
のようにしてHTTPのINPUTを許可した結果、iptables -Lでみると
Chain INPUT (policy DROP)
ACCEPT tcp -- anywhere anywhere tcp dpt:http
こうなります。
(表示される一覧に表示される"Chain INPUT"のところも注意して
見てください。INPUTなのかOUTPUTなのか、です)

INPUTは/etc/firewallをみていろいろと許可するよになっていますが、
OUTPUTの許可設定は何もなく、デフォルトでdropにされたままです。
何も出ていけません。
iptables -L では
Chain OUTPUT (policy DROP)
となっているはずです。

デフォルトポリシーでDROPになってるので、個別に許可してあげる
必要があります。

考え方や運用環境によりますが、個別に許可するんじゃなくて、
OUTPUTはデフォルトポリシー許可してもいいと思います。
DebianとかCentOSとかは、たしかそうやっていたような。。。

--
なかむら

Yamamotoです。

横から済みません。
一緒に作業している者ですが・・・

本来はFOMAアダプター経由でメール送信しようとしているのですが、現状は試験的にeth0を使用して試しています。

> ここまでのルールで、eth0以外はINPUTもOUTPUTも全て許可ですが、
> (余談ですが、eth0以外は入出力全て許可でいいのか?私は疑問です)
> eth0はデフォルトでINPUTもOUTPUTも全て非許可(DROP)です。

と言うことは、FOMAアダプター経由のppp接続で行った場合は、何も変更しなくてもメール送信できるということでしょうか?

中村です。

> Yamamotoです。
...
> と言うことは、FOMAアダプター経由のppp接続で行った場合は、何も変更しなくてもメール送信できるということでしょうか?

はい。ppp0は出入り自由だと思います。
USB-LANアダプタなどでeth1を追加した場合も同じですね。

私の場合ですが、FOMAなどで外部につなぐとき(ppp0)や、
2nd-LANを使うとき(eth1)は、それらが全部許可になるのは
気持ち悪いので、/etc/init.d/firewallの
# allow all non-external interfaces for everything
iptables -A INPUT -i ! $EXT -j ACCEPT
iptables -A OUTPUT -o ! $EXT -j ACCEPT
の部分を
# allow loopback interfaces for everything
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT
のように変更してppp0やeth1にも制限をかけるようにしてます。

でもって、rc.localなどでppp0やeth1のINPUTとOUTPUTの
設定をしてます。

--
なかむら

中村です。

> INPUTは/etc/firewallをみていろいろと許可するよになっていますが、
> OUTPUTの許可設定は何もなく、デフォルトでdropにされたままです。
> 何も出ていけません。

私が書いたこの部分を訂正します。

/etc/init.d/firewallの一番最後のところで、
# all protocols outgoing
iptables -A OUTPUT -o $EXT -j ACCEPT
と、OUPUTは全部許可しいるのを見落としてました。

iptables関連に手を入れていない状態(たぶん)の実機で
確認したところ、こうなってました。
(440ですけど460も同じだと思います)

[root@armadillo440-0 (ttymxc1) ~]# iptables -L -n
Chain INPUT (policy DROP)
target     prot opt source               destination
ACCEPT     0    --  0.0.0.0/0            0.0.0.0/0
ACCEPT     icmp --  0.0.0.0/0            0.0.0.0/0
ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:80
ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:23
ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:21
ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:161
ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:22
ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:20
REJECT     tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:113 reject-with icmp-port-unreachable
DROP       tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpts:6000:6010
ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpts:1024:65535
ACCEPT     udp  --  0.0.0.0/0            0.0.0.0/0           udp dpt:123
ACCEPT     udp  --  0.0.0.0/0            0.0.0.0/0           udp dpt:161
ACCEPT     udp  --  0.0.0.0/0            0.0.0.0/0           udp dpt:22
ACCEPT     udp  --  0.0.0.0/0            0.0.0.0/0           udp dpt:22222
ACCEPT     udp  --  0.0.0.0/0            0.0.0.0/0           udp dpts:1024:65535
 
Chain FORWARD (policy ACCEPT)
target     prot opt source               destination
 
Chain OUTPUT (policy DROP)
target     prot opt source               destination
ACCEPT     0    --  0.0.0.0/0            0.0.0.0/0
ACCEPT     0    --  0.0.0.0/0            0.0.0.0/0

最後のOUTPUTのChainのところで、全てACCEPTになってます。

ということで、質問者さんがこのあたりをいじっていなければ、
SMTPで接続できないのはこれが原因ではなさそうですね。

--
なかむら

いくつか整理させてください。

- armadillo とテスト用の Ubuntu は、同じ環境でテストしていますか? 違い
は、なにも無いですか?

- socket() から connect までのコードって、見
せてもらえますか? あまり connect() が EPERM を返すよう
に思えないので。

- man pageによれば、broadcast address へアクセスしようとすると EPERM
が返ることがあると記述されています。アクセスしようとしているサーバー
は、とりあえずテスト用だったりしますか? IPアドレスは大丈夫ですか?

- あと、他の人からの提案もあるように、iptable の設定も確認した方が良い
かもしれません。iptables -L -nで表示されたものを見せて
頂けますか?

- パケットのキャプチャーって、可能ですか?

yashiさん、中村です。

> - man pageによれば、broadcast address へアクセスしようとすると EPERM
> が返ることがあると記述されています。アクセスしようとしているサーバー

ATDE3でのman connectから引用

       EACCES, EPERM
              ソケットのブロードキャスト・フラグが有効になっていないのにユーザ
              がブロードキャストへ接続を試みた。または、ローカルのファイアウォ
              ールの規則により接続の要求が失敗した。

「ローカルのファイアウォールの規則」の場合もあるようです。
これがiptablesかな?

でも・・・2つ前の私の訂正のように、
iptablesは問題はなさそうな気もしてます。

--
なかむら

いつもお世話になります。
向井です。

諸事情によりかなり返信が遅くなってしまい申し訳有りません。
皆様いろいろご回答ありがとうございます。
現状はまだメール送信できておりません。
(同じ症状のままです)

> - armadillo とテスト用の Ubuntu は、同じ環境でテストしていますか? 違い
> は、なにも無いですか?
→ armadilloはボード上、Ubuntuはpc上から、作成したメール送信のプログラムを走らせています。
ですので環境としてはだいぶ違いがあります。

> - socket() から connect までのコードって、見
> せてもらえますか? あまり connect() が EPERM を返すよう
> に思えないので。
→ 添付ファイルに関連箇所を抜粋したところのソースコードを添付させていただきます。

> - man pageによれば、broadcast address へアクセスしようとすると EPERM
> が返ることがあると記述されています。アクセスしようとしているサーバー
> は、とりあえずテスト用だったりしますか? IPアドレスは大丈夫ですか?
→ アクセスしようとしているサーバは社内でメールを使う為に設定しているSMTPのサーバです。
gethostbyname()でとってきたIPアドレスを確認する限りは大丈夫でした。
(添付していますファイルにコメントを入れてあります)

> - あと、他の人からの提案もあるように、iptable の設定も確認した方が良い
> かもしれません。iptables -L -nで表示されたものを見せて
> 頂けますか?
→ このレスの次レスの中村様が記載していただいているログ内容と一致します。
firewall関連の設定ファイルは全く触っておりません。

> - パケットのキャプチャーって、可能ですか?
→ 申し訳有りませんがちょっと無理そうです。

以上、よろしくお願いします。

> いくつか整理させてください。
>
> - armadillo とテスト用の Ubuntu は、同じ環境でテストしていますか? 違い
> は、なにも無いですか?
>
> - socket() から connect までのコードって、見
> せてもらえますか? あまり connect() が EPERM を返すよう
> に思えないので。
>
> - man pageによれば、broadcast address へアクセスしようとすると EPERM
> が返ることがあると記述されています。アクセスしようとしているサーバー
> は、とりあえずテスト用だったりしますか? IPアドレスは大丈夫ですか?
>
> - あと、他の人からの提案もあるように、iptable の設定も確認した方が良い
> かもしれません。iptables -L -nで表示されたものを見せて
> 頂けますか?
>
> - パケットのキャプチャーって、可能ですか?

ファイル ファイルの説明
mailサンプル.txt

いつもお世話になります。
向井です。

h_errnoの見方をMANに載ってあった通りにhstrerror( h_errno )で出してみると、
gethostbyname()でh_errno=(Unknown host)となっている事がわかりました。
(NULLではありません)

ただ戻り値をみると、ホストの正式名(h_name)、ホストのネットワークアドレス(h_addr_list)を確認する限りは
こちらの期待値が返って来ています。

この取得した情報をconnect()に渡すとh_errno=(Unknown host)のままでエラーとなっています。

iptable関連のファイルの中身も確認しましたが、皆様にご指摘いただいた通りの設定(defaultの設定)のようです。

他に何か注意すべき所があればご指摘下さい。

以上、よろしくお願いします。

> > - armadillo とテスト用の Ubuntu は、同じ環境でテストしていますか? 違い
> > は、なにも無いですか?
> → armadilloはボード上、Ubuntuはpc上から、作成したメール送信のプログラムを走らせています。
> ですので環境としてはだいぶ違いがあります。

プログラム実行環境ではなく、ネットワークという意味でした。

> > - socket() から connect までのコードって、見
> > せてもらえますか? あまり connect() が EPERM を返すよう
> > に思えないので。
> → 添付ファイルに関連箇所を抜粋したところのソースコードを添付させていただきます。

ありがとうございます。PORTは、587 なんですね。

> > - man pageによれば、broadcast address へアクセスしようとすると EPERM
> > が返ることがあると記述されています。アクセスしようとしているサーバー
> > は、とりあえずテスト用だったりしますか? IPアドレスは大丈夫ですか?
> → アクセスしようとしているサーバは社内でメールを使う為に設定しているSMTPのサーバです。
> gethostbyname()でとってきたIPアドレスを確認する限りは大丈夫でした。
> (添付していますファイルにコメントを入れてあります)

なるほど。

なんとなく、SMTPサーバーに嫌われているのかな〜と思うのですが...。

- SMTPサーバーではなく、Armadilloから他のサーバー (たとえば、
google.com:80とか、社内 webサーバーとか)にアクセスできますか? もしア
クセスできたら、armadillo 側の問題じゃない気がします。このパターンで
気になるのが、最初の質問である「ネットワーク環境」です。まずは、
Armadillo がどこかのネットワークサーバーに接続できることを確認してみ
たいです。コードを読むかぎり、SMTPに特化していないエラーに見えるので。

- telnet で SMTP サーバーの587番ポートへのアクセスできますか? 自作プロ
グラムが悪いのか、そもそもアクセスできないのかの切り分けになると思い
ます。

- SMTPサーバーのログを管理者の人に依頼して確認することはできますか? ネッ
トワーク環境に差がないのに、Armadillo 側だけエラーになるのであれば、
SMTPサーバーがセキュリティー的な面からアクセス拒否をしている可能性が
あります。なので、サーバー管理者に聞いてみると良いかもしれません。