Java POIでWord(.docx)ファイルを作る
はじめに
事前に以下のライブラリを用意します。
- Apache POI
- https://poi.apache.org/download.html
- ※"poi-bin-3.13-20150929.tar.gz"のリンクからダウンロード
今回のサンプルは以下のjarがあれば動作します。
- poi-3.13-20150929.jar
- poi-ooxml-3.13-20150929.jar
- poi-ooxml-schemas-3.13-20150929.jar
- xmlbeans-2.6.0.jar
実装例
今回のサンプルでは以下の機能を確認します。
少しあっさりしていますがまずはこれぐらいで。 動作確認しやすいようにmainメソッドで実行できるようにしてあります。
import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import org.apache.poi.xwpf.usermodel.XWPFDocument; import org.apache.poi.xwpf.usermodel.XWPFParagraph; import org.apache.poi.xwpf.usermodel.XWPFRun; import org.apache.poi.xwpf.usermodel.XWPFTable; /** * * @author tool-taro.com */ public class DOCXWriteTest { public static void main(String[] args) throws FileNotFoundException, IOException { String outputFilePath = "out.docx"; XWPFDocument document = null; XWPFTable table; XWPFParagraph paragraph; XWPFRun run; FileOutputStream fout = null; try { document = new XWPFDocument(); //普通の段落を2つ作る for (int i = 0; i < 2; i++) { paragraph = document.createParagraph(); //それぞれの段落の中に色の異なるテキストを2種配置する //setText内で\nを指定しても改行されないので注意、改行するには必ず段落を作る run = paragraph.createRun(); run.setFontFamily("MS ゴシック"); run.setText("黒のテキスト"); run = paragraph.createRun(); run.setFontFamily("MS ゴシック"); run.setColor("ff0000"); run.setText("赤のテキスト"); } //2x2の表を作る table = document.createTable(2, 2); for (int i = 0; i < 2; i++) { for (int j = 0; j < 2; j++) { //それぞれのセルの中に段落を2つ作る for (int k = 0; k < 2; k++) { //セルには初期状態で1つの段落がある(実装が変わるかもしれないので念のため存在数を確認して適切に処理) if (table.getRow(i).getCell(j).getParagraphs().size() > k) { paragraph = table.getRow(i).getCell(j).getParagraphs().get(k); } else { paragraph = table.getRow(i).getCell(j).addParagraph(); } //それぞれの段落の中に色の異なるテキストを2種配置する run = paragraph.createRun(); run.setFontFamily("MS ゴシック"); run.setText("黒のテキスト"); run = paragraph.createRun(); run.setFontFamily("MS ゴシック"); run.setColor("ff0000"); run.setText("赤のテキスト"); } } } //ファイル出力 fout = new FileOutputStream(outputFilePath); document.write(fout); } finally { if (fout != null) { try { fout.close(); } catch (Exception e) { } } if (document != null) { try { document.close(); } catch (Exception e) { } } } } }
動作確認
$ javac DOCXWriteTest.java $ java DOCXWriteTest
作成されたファイルはこんな感じになりました。
環境
上記の実装をベースにWebツールも公開しています。 Diff(テキスト差分チェック)|Web便利ツール@ツールタロウ
MuninでTomcatのモニタリング
はじめに
MuninでTomcatをモニタリングします。 MuninやTomcatはすでにインストールされている前提で、 Tomcat側の受け入れ設定とMunin側の監視設定をします。
Tomcat本体の設定は、過去の記事の通りで、 Muninはポート8080を経由してTomcat側のデータを取得します。
環境
手順
Tomcat側にユーザ・ユーザ権限の追加
$ vi $TOMCAT_HOME/conf/tomcat-users.xml
<tomcat-users...> (省略) # 追記 <role rolename="manager-status"/> <user username="munin" password="munin" roles="manager-status"/> </tomcat-users>
Tomcatを再起動し、監視用のI/Fにアクセスできるか確認します。
$ curl --user munin:munin http://localhost:8080/manager/status?XML=true <?xml version="1.0" encoding="utf-8"?><?xml-stylesheet type="text/xsl" href="/manager/xform.xsl" ?> <status><jvm><memory free='112838232' total='261750784' max='261750784'/>(省略)</status>
Muninの監視用プラグイン等のインストール・配置
$ yum install munin-java-plugins $ ln -s /usr/share/munin/plugins/tomcat_access /etc/munin/plugins/ $ ln -s /usr/share/munin/plugins/tomcat_jvm /etc/munin/plugins/ $ ln -s /usr/share/munin/plugins/tomcat_threads /etc/munin/plugins/ $ ln -s /usr/share/munin/plugins/tomcat_volume /etc/munin/plugins/ $ yum install perl-XML-Simple
MuninのTomcat監視設定
$ vi /etc/munin/plugin-conf.d/munin-node
# 設定ファイル追記 [tomcat*] env.host localhost env.port 8080 env.request /manager/status?XML=true env.user munin env.password munin env.timeout 30 env.connector "http-nio-8080"
Muninの設定反映・再起動(必要に応じて)
$ munin-node-configure --shell | sh -x $ systemctl restart munin-node
動作確認
次回以降のグラフ生成のタイミングでTomcatのグラフが生成されていることを確認します。
Webツールも公開しています。 Web便利ツール@ツールタロウ
Java FacebookのOGPキャッシュクリア
はじめに
というかHttpClientの使い方、といったところですが・・。 事前に以下のライブラリを用意します。
- HttpClient
- https://hc.apache.org/downloads.cgi
- ※"4.5.1.tar.gz"のリンクからダウンロード
- HttpCore
- https://hc.apache.org/downloads.cgi
- ※"4.4.4.tar.gz"のリンクからダウンロード
今回のサンプルは以下のjarがあれば動作します。
- httpclient-4.5.1.jar
- httpcore-4.4.4.jar
実装例
サンプルでは、動作確認しやすいようにmainメソッドで実行できるようにしてあります。 結果だけを確認したい場合は、この記事の一番下のリンク先で使えるようにしてありますのでご覧ください。
import java.io.BufferedInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.List; import org.apache.http.Header; import org.apache.http.NameValuePair; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpPost; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.message.BasicHeader; import org.apache.http.message.BasicNameValuePair; /** * * @author tool-taro.com */ public class ScrapeOgp { public static void main(String[] args) throws UnsupportedEncodingException, IOException { //クリアしたいURL String url = "http://.../"; //ユーザエージェント String userAgent = "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:43.0) Gecko/20100101 Firefox/43.0"; //タイムアウト(ミリ秒) int timeout = 10000; //クリアリクエスト処理 ByteArrayOutputStream bout = new ByteArrayOutputStream(); List<Header> headers = new ArrayList<>(); if (userAgent != null) { headers.add(new BasicHeader("User-Agent", userAgent)); } RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(timeout).setConnectTimeout(timeout).setCircularRedirectsAllowed(true).setRedirectsEnabled(true).build(); CloseableHttpClient httpclient = HttpClientBuilder.create().setDefaultRequestConfig(requestConfig).setDefaultHeaders(headers).build(); HttpPost httpPost = new HttpPost("https://graph.facebook.com/"); List<NameValuePair> requestParams = new ArrayList<>(); requestParams.add(new BasicNameValuePair("id", url)); requestParams.add(new BasicNameValuePair("scrape", "true")); httpPost.setEntity(new UrlEncodedFormEntity(requestParams)); CloseableHttpResponse response = null; BufferedInputStream in = null; try { response = httpclient.execute(httpPost); in = new BufferedInputStream(response.getEntity().getContent()); byte[] buf = new byte[1024]; int length; while (true) { length = in.read(buf); if (length == -1) { break; } bout.write(buf, 0, length); } } finally { if (in != null) { try { in.close(); } catch (Exception e) { } } if (response != null) { try { response.close(); } catch (Exception e) { } } } //標準出力 System.out.format("リクエスト結果=%1$s", new String(bout.toByteArray(), "UTF-8")); } }
動作確認
$ javac ScrapeOgp.java $ java ScrapeOgp $ リクエスト結果={ "url": ...(省略)
なお、リクエストを送信しても、Facebook側の状況次第では受け付けられない・反映されないケースがあります。ご注意ください。
環境
上記の実装をベースにWebツールも公開しています。 FacebookのOGPキャッシュクリア|Web便利ツール@ツールタロウ
Cloudnの仮想サーバー(FLATタイプ)プラン vQ (月々税抜450円)で固定IPアドレスをゲットする(OpenVPNサーバを作る)
はじめに
前回(さくらのVPS512(月々税抜635円)で固定IPアドレスをゲットする(OpenVPNサーバを作る))に引き続き、今回は非常に安価な最小プランで知られるCloudnでVPNサーバを立ち上げる手順をまとめます。
作業前提(自己責任でご判断ください)
- 今回は「Cloudnの仮想サーバー(FLATタイプ)プラン vQ (月々税抜450円 2016/02/15現在)」を使う
- CentOS7.1
- OpenVPN
- ほかの機能(Webサーバ等)は一切設けない
- 複数人で使えるようにする
- 説明の簡略化のため、ほぼすべてrootで作業
- コマンドの入力、viによるファイルの編集などがあり、漏れなく作業が必要
- 契約・請求・キャンセル方法等については、エヌ・ティ・ティ・コミュニケーションズ株式会社からの案内に従ってください
問題なければ始めましょう。
作業手順
アカウント登録
パブリッククラウドサービス Cloudnの「サービス申込み」ページからアカウント・決済方法などを登録してください。手順は省略します。
ログイン
ポータルサイトからログインして「FLATタイプ Compute」のコンソールに入ります。
ネットワークの設定(セキュリティグループ)
メニューの「ネットワーク」を選び、ビューの選択で「セキュリティグループ」を選んでください。
一覧に表示されている「default」をクリックし、図のように設定を追加します。
サーバの追加
メニューの「仮想サーバー」を選び、「+仮想サーバーの追加」を選んでください。
以下のように順に次に進みます。
仮想サーバの追加が終わると、図のようなダイアログが出て、rootのパスワードが通知されます。1度しか通知されませんので必ずメモしておきましょう。
追加されたサーバの詳細からIPアドレスも確認します。
SSHログイン
ここから先はSSH経由で作業します。 WindowsならTeraTermなど、Macならターミナルなどでログインしてください。 ログイン先のサーバは上記のサーバの詳細で確認したIPアドレス、ユーザはroot、パスワードはサーバ追加時に設定したパスワードです。
rootパスワードの設定
ここから先はすべてrootで作業します。 先ほど設定したrootのパスワードが気に入らない場合は修正しておきましょう。
$ passwd root Changing password for user root. New password:パスワード入力 Retype new password:パスワード再入力 passwd: all authentication tokens updated successfully.
SELinuxの無効化
"SELINUX=disabled"となっている場合は変更の必要がありません。先に進みましょう。
$ vi /etc/selinux/config
#SELINUX=enforcing SELINUX=disabled
SSHログイン用ユーザの追加
SSHでログインする際、最初からrootでログインするのはセキュアではないため、 別のユーザを作り、パスワードを設定します。 今後は、別ユーザでログインしてからrootになる、という流れを作るわけです。
$ useradd sshuser $ passwd sshuser Changing password for user sshuser. New password:パスワード入力 Retype new password:パスワード再入力 passwd: all authentication tokens updated successfully.
rootでのSSHログインの無効化
SSHでログインする際、rootでのログインを許可しないように設定します。
$ vi /etc/ssh/sshd_config
#PermitRootLogin yes PermitRootLogin no
変更を反映します。
$ systemctl restart sshd.service
次回以降のログインの流れについて触れておきます。 先ほど作ったsshuserでログインした後、rootになるには以下のように入力します。
$ su - Password:パスワード入力
sshuserでログインする流れを確認したところで、 SELinuxの設定変更の反映もしておきたいので、サーバを再起動します。
$ reboot
再度SSHでアクセスできるようになったら、sshuserでログインし、rootになります。
IPフォワーディングの有効化
$ vi /etc/sysctl.d/10-ipv4.conf
#追記 net.ipv4.ip_forward = 1
変更を反映します。
$ sysctl -p /etc/sysctl.d/10-ipv4.conf net.ipv4.ip_forward = 1
openvpnのインストール
$ yum -y install epel-release $ yum -y install openvpn $ yum -y install unzip
この後、設定をしていくわけですが、先にパスワードを1つ決めておいてください。 各種証明書の作成時などに使います。 パスワード(A)とします。
CA証明書・秘密鍵の作成
$ cd /usr/local/src/ $ wget https://github.com/OpenVPN/easy-rsa/archive/master.zip $ unzip master.zip $ cp -r easy-rsa-master/easyrsa3/ /etc/openvpn/ $ rm -fr easy-rsa-master/ $ cd /etc/openvpn/easyrsa3/ $ ./easyrsa init-pki init-pki complete; you may now create a CA or requests. Your newly created PKI dir is: /etc/openvpn/easyrsa3/pki $ ./easyrsa build-ca Generating a 2048 bit RSA private key ............................................................................................+++ .................................................+++ writing new private key to '/etc/openvpn/easyrsa3/pki/private/ca.key.XXXXXXXXXX' Enter PEM pass phrase:パスワード(A)入力 Verifying - Enter PEM pass phrase:パスワード(A)再入力 ----- You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Common Name (eg: your user, host, or server name) [Easy-RSA CA]:サーバ名入力(例: vpnserver) CA creation complete and you may now import and sign cert requests. Your new CA certificate file for publishing is at: /etc/openvpn/easyrsa3/pki/ca.crt $ cp pki/ca.crt /etc/openvpn/
サーバ証明書・秘密鍵の作成
$ ./easyrsa build-server-full server nopass Generating a 2048 bit RSA private key ...................................................+++ ...............................................................................+++ writing new private key to '/etc/openvpn/easyrsa3/pki/private/server.key.e7omRJmwXu' ----- Using configuration from /etc/openvpn/easyrsa3/openssl-1.0.cnf Enter pass phrase for /etc/openvpn/easyrsa3/pki/private/ca.key:パスワード(A)入力 Check that the request matches the signature Signature ok The Subject's Distinguished Name is as follows commonName :PRINTABLE:'server' Certificate is to be certified until Feb 3 04:11:41 2026 GMT (3650 days) Write out database with 1 new entries Data Base Updated $ cp pki/issued/server.crt /etc/openvpn/ $ cp pki/private/server.key /etc/openvpn/
DHパラメータの作成
$ ./easyrsa gen-dh Generating DH parameters, 2048 bit long safe prime, generator 2 This is going to take a long time (省略) DH parameters of size 2048 created at /etc/openvpn/easyrsa3/pki/dh.pem $ cp pki/dh.pem /etc/openvpn/
クライアント証明書(ダミー)の作成
$ ./easyrsa build-client-full dmy nopass Generating a 2048 bit RSA private key ..................+++ ..................+++ writing new private key to '/etc/openvpn/easyrsa3/pki/private/dmy.key.XXXXXXXXXX' ----- Using configuration from /etc/openvpn/easyrsa3/openssl-1.0.cnf Enter pass phrase for /etc/openvpn/easyrsa3/pki/private/ca.key:パスワード(A)入力 Check that the request matches the signature Signature ok The Subject's Distinguished Name is as follows commonName :PRINTABLE:'dmy' Certificate is to be certified until Feb 3 04:14:46 2026 GMT (3650 days) Write out database with 1 new entries Data Base Updated $ ./easyrsa revoke dmy Please confirm you wish to revoke the certificate with the following subject: subject= commonName = dmy Type the word 'yes' to continue, or any other input to abort. Continue with revocation: yes Using configuration from /etc/openvpn/easyrsa3/openssl-1.0.cnf Enter pass phrase for /etc/openvpn/easyrsa3/pki/private/ca.key:パスワード(A)入力 Revoking Certificate 02. Data Base Updated IMPORTANT!!! Revocation was successful. You must run gen-crl and upload a CRL to your infrastructure in order to prevent the revoked cert from being accepted. $ ./easyrsa gen-crl Using configuration from /etc/openvpn/easyrsa3/openssl-1.0.cnf Enter pass phrase for /etc/openvpn/easyrsa3/pki/private/ca.key:パスワード(A)入力 An updated CRL has been created. CRL file: /etc/openvpn/easyrsa3/pki/crl.pem $ cp pki/crl.pem /etc/openvpn/ $ chmod o+r /etc/openvpn/crl.pem
OpenVPNの設定
$ vi /etc/openvpn/server.conf
port 1194 proto udp dev tun ca ca.crt cert server.crt key server.key # This file should be kept secret dh dh.pem server 192.168.100.0 255.255.255.0 ifconfig-pool-persist ipp.txt push "redirect-gateway def1" fragment 1280 mssfix 1280 link-mtu 1400 client-to-client keepalive 10 120 comp-lzo user nobody group nobody persist-key persist-tun status openvpn-status.log log-append /var/log/openvpn.log verb 3 crl-verify crl.pem
サービスの登録・起動
$ systemctl enable openvpn@server.service Created symlink from /etc/systemd/system/multi-user.target.wants/openvpn@server.service to /usr/lib/systemd/system/openvpn@.service. $ systemctl start openvpn@server.service
Firewallの起動・設定
$ systemctl enable firewalld Created symlink from /etc/systemd/system/dbus-org.fedoraproject.FirewallD1.service to /usr/lib/systemd/system/firewalld.service. Created symlink from /etc/systemd/system/basic.target.wants/firewalld.service to /usr/lib/systemd/system/firewalld.service. $ systemctl start firewalld $ firewall-cmd --permanent --zone=public --add-masquerade $ firewall-cmd --permanent --zone=public --add-port=1194/udp $ firewall-cmd --reload $ firewall-cmd --list-all public (default, active) interfaces: eth0 sources: services: dhcpv6-client ssh ports: 1194/udp masquerade: yes forward-ports: icmp-blocks: rich rules:
クライアント証明書・秘密鍵の作成
複数ユーザ分を作る場合は繰り返してください。
$ cd /etc/openvpn/easyrsa3/ $ ./easyrsa build-client-full ユーザ名 Generating a 2048 bit RSA private key ...............................................................+++ ...................................+++ writing new private key to '/etc/openvpn/easyrsa3/pki/private/ユーザ名.key.XXXXXXXXXX' Enter PEM pass phrase:ユーザ個別のパスワード入力 Verifying - Enter PEM pass phrase:ユーザ個別のパスワード再入力 ----- Using configuration from /etc/openvpn/easyrsa3/openssl-1.0.cnf Enter pass phrase for /etc/openvpn/easyrsa3/pki/private/ca.key:パスワード(A)入力 Check that the request matches the signature Signature ok The Subject's Distinguished Name is as follows commonName :T61STRING:'ユーザ名' Certificate is to be certified until Feb 3 04:25:02 2026 GMT (3650 days) Write out database with 1 new entries Data Base Updated $ cp /etc/openvpn/ca.crt /home/sshuser/ $ cp /etc/openvpn/easyrsa3/pki/issued/ユーザ名.crt /home/sshuser/ $ cp /etc/openvpn/easyrsa3/pki/private/ユーザ名.key /home/sshuser/ $ chown sshuser:sshuser /home/sshuser/ca.crt $ chown sshuser:sshuser /home/sshuser/ユーザ名.crt $ chown sshuser:sshuser /home/sshuser/ユーザ名.key
各証明書・秘密鍵のユーザへの配布
一つ前の手順で/home/sshuser以下に設置しましたので、 SFTPなどでログインしてダウンロードするとよいでしょう。
ca.crt ユーザ名.crt ユーザ名.key
また、下記の情報も伝えます。
ユーザ名 ユーザ個別のパスワード
クライアントの接続設定
過去の記事を参考にしてください。
接続の確認
接続が完了したら、自分のIPアドレス確認用のサイトに行って確認してみましょう。 Cloudnで与えられたサーバのIPアドレスになっていたら成功です。 IPアドレス確認|Web便利ツール@ツールタロウ
さいごに
必要最小限の作業にとどめたつもりでいるのですが、課題は色々あると思います。
例えば、
- SSHはどこからでも接続できてしまう(→Firewallで閉じ、普段はCloudnのコンソールから作業する等の対応は可能)
- このサーバの状態を監視する手段がない
などです。
適宜、環境に合わせて追加・変更していただき、快適な運用をしていただければ幸いです。 ここまでお付き合いいただきましてありがとうございました。
Webツールも公開しています。 Web便利ツール@ツールタロウ
ConoHaの最小プラン(月々税抜900円)で固定IPアドレスをゲットする(OpenVPNサーバを作る)
はじめに
前回(さくらのVPS512(月々税抜635円)で固定IPアドレスをゲットする(OpenVPNサーバを作る))に引き続き、今回はパフォーマンスが評判のConoHaでVPNサーバを立ち上げる手順をまとめます。
作業前提(自己責任でご判断ください)
- 今回は「ConoHa 最小プラン(月々税抜900円 2016/02/15現在)」を使う
- CentOS7.2
- OpenVPN
- ほかの機能(Webサーバ等)は一切設けない
- 複数人で使えるようにする
- 説明の簡略化のため、ほぼすべてrootで作業
- コマンドの入力、viによるファイルの編集などがあり、漏れなく作業が必要
- 契約・請求・キャンセル方法等については、GMOインターネット株式会社からの案内に従ってください
問題なければ始めましょう。
作業手順
アカウント登録
ConoHaの「お申し込み」ページからアカウント・決済方法などを登録してください。手順は省略します。
ログイン・サーバ追加
ログインしてメニューの「サーバー」をクリックして、「サーバーリスト」を表示させてみます。 右上の「+サーバー」でサーバを追加しましょう。
設定は下記のようにセットしてください。今回はIPv6を使用しないようにしています。
サーバ一覧の確認
サーバの追加はあっという間に終わります。
サーバの詳細を確認してみましょう。
SSHログイン
ここから先はSSH経由で作業します。 WindowsならTeraTermなど、Macならターミナルなどでログインしてください。 ログイン先のサーバは上記のサーバの詳細で確認したIPアドレス、ユーザはroot、パスワードはサーバ追加時に設定したパスワードです。
rootパスワードの設定
ここから先はすべてrootで作業します。 先ほど設定したrootのパスワードが気に入らない場合は修正しておきましょう。
$ passwd root Changing password for user root. New password:パスワード入力 Retype new password:パスワード再入力 passwd: all authentication tokens updated successfully.
SELinuxの無効化
"SELINUX=disabled"となっている場合は変更の必要がありません。先に進みましょう。
$ vi /etc/selinux/config
SELINUX=disabled
SSHログイン用ユーザの追加
SSHでログインする際、最初からrootでログインするのはセキュアではないため、 別のユーザを作り、パスワードを設定します。 今後は、別ユーザでログインしてからrootになる、という流れを作るわけです。
$ useradd sshuser $ passwd sshuser Changing password for user sshuser. New password:パスワード入力 Retype new password:パスワード再入力 passwd: all authentication tokens updated successfully.
rootでのSSHログインの無効化
SSHでログインする際、rootでのログインを許可しないように設定します。
$ vi /etc/ssh/sshd_config
#PermitRootLogin yes PermitRootLogin no
変更を反映します。
$ systemctl restart sshd.service
次回以降のログインの流れについて触れておきます。 先ほど作ったsshuserでログインした後、rootになるには以下のように入力します。
$ su - Password:パスワード入力
sshuserでログインする流れを確認したところで、 SELinuxの設定変更の反映もしておきたいので、サーバを再起動します。
$ reboot
再度SSHでアクセスできるようになったら、sshuserでログインし、rootになります。
IPフォワーディングの有効化
$ vi /etc/sysctl.d/10-ipv4.conf
#追記 net.ipv4.ip_forward = 1
変更を反映します。
$ sysctl -p /etc/sysctl.d/10-ipv4.conf net.ipv4.ip_forward = 1
openvpnのインストール
$ yum -y install openvpn
この後、設定をしていくわけですが、先にパスワードを1つ決めておいてください。 各種証明書の作成時などに使います。 パスワード(A)とします。
CA証明書・秘密鍵の作成
$ cd /usr/local/src/ $ wget https://github.com/OpenVPN/easy-rsa/archive/master.zip $ unzip master.zip $ cp -r easy-rsa-master/easyrsa3/ /etc/openvpn/ $ rm -fr easy-rsa-master/ $ cd /etc/openvpn/easyrsa3/ $ ./easyrsa init-pki init-pki complete; you may now create a CA or requests. Your newly created PKI dir is: /etc/openvpn/easyrsa3/pki $ ./easyrsa build-ca Generating a 2048 bit RSA private key ............................................................................................+++ .................................................+++ writing new private key to '/etc/openvpn/easyrsa3/pki/private/ca.key.XXXXXXXXXX' Enter PEM pass phrase:パスワード(A)入力 Verifying - Enter PEM pass phrase:パスワード(A)再入力 ----- You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Common Name (eg: your user, host, or server name) [Easy-RSA CA]:サーバ名入力(例: vpnserver) CA creation complete and you may now import and sign cert requests. Your new CA certificate file for publishing is at: /etc/openvpn/easyrsa3/pki/ca.crt $ cp pki/ca.crt /etc/openvpn/
サーバ証明書・秘密鍵の作成
$ ./easyrsa build-server-full server nopass Generating a 2048 bit RSA private key ...................................................+++ ...............................................................................+++ writing new private key to '/etc/openvpn/easyrsa3/pki/private/server.key.e7omRJmwXu' ----- Using configuration from /etc/openvpn/easyrsa3/openssl-1.0.cnf Enter pass phrase for /etc/openvpn/easyrsa3/pki/private/ca.key:パスワード(A)入力 Check that the request matches the signature Signature ok The Subject's Distinguished Name is as follows commonName :PRINTABLE:'server' Certificate is to be certified until Feb 3 04:11:41 2026 GMT (3650 days) Write out database with 1 new entries Data Base Updated $ cp pki/issued/server.crt /etc/openvpn/ $ cp pki/private/server.key /etc/openvpn/
DHパラメータの作成
$ ./easyrsa gen-dh Generating DH parameters, 2048 bit long safe prime, generator 2 This is going to take a long time (省略) DH parameters of size 2048 created at /etc/openvpn/easyrsa3/pki/dh.pem $ cp pki/dh.pem /etc/openvpn/
クライアント証明書(ダミー)の作成
$ ./easyrsa build-client-full dmy nopass Generating a 2048 bit RSA private key ..................+++ ..................+++ writing new private key to '/etc/openvpn/easyrsa3/pki/private/dmy.key.XXXXXXXXXX' ----- Using configuration from /etc/openvpn/easyrsa3/openssl-1.0.cnf Enter pass phrase for /etc/openvpn/easyrsa3/pki/private/ca.key:パスワード(A)入力 Check that the request matches the signature Signature ok The Subject's Distinguished Name is as follows commonName :PRINTABLE:'dmy' Certificate is to be certified until Feb 3 04:14:46 2026 GMT (3650 days) Write out database with 1 new entries Data Base Updated $ ./easyrsa revoke dmy Please confirm you wish to revoke the certificate with the following subject: subject= commonName = dmy Type the word 'yes' to continue, or any other input to abort. Continue with revocation: yes Using configuration from /etc/openvpn/easyrsa3/openssl-1.0.cnf Enter pass phrase for /etc/openvpn/easyrsa3/pki/private/ca.key:パスワード(A)入力 Revoking Certificate 02. Data Base Updated IMPORTANT!!! Revocation was successful. You must run gen-crl and upload a CRL to your infrastructure in order to prevent the revoked cert from being accepted. $ ./easyrsa gen-crl Using configuration from /etc/openvpn/easyrsa3/openssl-1.0.cnf Enter pass phrase for /etc/openvpn/easyrsa3/pki/private/ca.key:パスワード(A)入力 An updated CRL has been created. CRL file: /etc/openvpn/easyrsa3/pki/crl.pem $ cp pki/crl.pem /etc/openvpn/ $ chmod o+r /etc/openvpn/crl.pem
OpenVPNの設定
$ vi /etc/openvpn/server.conf
port 1194 proto udp dev tun ca ca.crt cert server.crt key server.key # This file should be kept secret dh dh.pem server 192.168.100.0 255.255.255.0 ifconfig-pool-persist ipp.txt push "redirect-gateway def1" push "dhcp-option DNS 157.7.180.133" # ConoHa DNS1 push "dhsp-option DNS 210.157.3.4" # ConoHa DNS2 fragment 1280 mssfix 1280 link-mtu 1400 client-to-client keepalive 10 120 comp-lzo user nobody group nobody persist-key persist-tun status openvpn-status.log log-append /var/log/openvpn.log verb 3 crl-verify crl.pem
サービスの登録・起動
$ systemctl enable openvpn@server.service Created symlink from /etc/systemd/system/multi-user.target.wants/openvpn@server.service to /usr/lib/systemd/system/openvpn@.service. $ systemctl start openvpn@server.service
Firewallの設定
$ firewall-cmd --permanent --zone=public --add-masquerade $ firewall-cmd --permanent --zone=public --add-port=1194/udp $ firewall-cmd --reload $ firewall-cmd --list-all public (default, active) interfaces: eth0 sources: services: dhcpv6-client ssh ports: 1194/udp masquerade: yes forward-ports: icmp-blocks: rich rules:
クライアント証明書・秘密鍵の作成
複数ユーザ分を作る場合は繰り返してください。
$ cd /etc/openvpn/easyrsa3/ $ ./easyrsa build-client-full ユーザ名 Generating a 2048 bit RSA private key ...............................................................+++ ...................................+++ writing new private key to '/etc/openvpn/easyrsa3/pki/private/ユーザ名.key.XXXXXXXXXX' Enter PEM pass phrase:ユーザ個別のパスワード入力 Verifying - Enter PEM pass phrase:ユーザ個別のパスワード再入力 ----- Using configuration from /etc/openvpn/easyrsa3/openssl-1.0.cnf Enter pass phrase for /etc/openvpn/easyrsa3/pki/private/ca.key:パスワード(A)入力 Check that the request matches the signature Signature ok The Subject's Distinguished Name is as follows commonName :T61STRING:'ユーザ名' Certificate is to be certified until Feb 3 04:25:02 2026 GMT (3650 days) Write out database with 1 new entries Data Base Updated $ cp /etc/openvpn/ca.crt /home/sshuser/ $ cp /etc/openvpn/easyrsa3/pki/issued/ユーザ名.crt /home/sshuser/ $ cp /etc/openvpn/easyrsa3/pki/private/ユーザ名.key /home/sshuser/ $ chown sshuser:sshuser /home/sshuser/ca.crt $ chown sshuser:sshuser /home/sshuser/ユーザ名.crt $ chown sshuser:sshuser /home/sshuser/ユーザ名.key
各証明書・秘密鍵のユーザへの配布
一つ前の手順で/home/sshuser以下に設置しましたので、 SFTPなどでログインしてダウンロードするとよいでしょう。
ca.crt ユーザ名.crt ユーザ名.key
また、下記の情報も伝えます。
ユーザ名 ユーザ個別のパスワード
クライアントの接続設定
過去の記事を参考にしてください。
接続の確認
接続が完了したら、自分のIPアドレス確認用のサイトに行って確認してみましょう。 ConoHaで与えられたサーバのIPアドレスになっていたら成功です。 IPアドレス確認|Web便利ツール@ツールタロウ
さいごに
必要最小限の作業にとどめたつもりでいるのですが、課題は色々あると思います。
例えば、
- SSHはどこからでも接続できてしまう(→Firewallで閉じ、普段はConoHaのコンソールから作業する等の対応は可能)
- このサーバの状態を監視する手段がない
などです。
適宜、環境に合わせて追加・変更していただき、快適な運用をしていただければ幸いです。 ここまでお付き合いいただきましてありがとうございました。
Webツールも公開しています。 Web便利ツール@ツールタロウ
Java AA→画像 (画像→AAの続き)
はじめに
前回、画像からアスキーアートを生成しましたので、 続きでアスキーアートを画像に戻します。
実装例
サンプルでは、動作確認しやすいようにmainメソッドで実行できるようにしてあります。 ソースコードは前回のものに処理を付け足す形としました("ここから追加分"の記述箇所以降)。 結果だけを確認したい場合は、この記事の一番下のリンク先で使えるようにしてありますのでご覧ください。
import java.awt.Color; import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics2D; import java.awt.GraphicsEnvironment; import java.awt.image.BufferedImage; import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import javax.imageio.ImageIO; /** * * @author tool-taro.com */ public class ImageToAscii { public static void main(String[] args) throws IOException, InterruptedException { //Javaのパス //String javaPath = "/usr/java/latest/bin/java"; String javaPath = "C:\\Program Files\\Java\\jdk1.8.0_74\\bin\\java.exe"; //jave5のディレクトリ String javeDir = "/usr/local/jave5"; //jave5.jarのパス String javePath = "/usr/local/jave5/jave5.jar"; //読み取りたい画像ファイルの保存場所 String inputFilePath = "input.jpg"; //Ascii文字数(横) int width = 200; String[] commandArray = new String[6]; int index = 0; commandArray[index++] = javaPath; commandArray[index++] = "-jar"; commandArray[index++] = javePath; commandArray[index++] = "image2ascii"; commandArray[index++] = inputFilePath; commandArray[index++] = "width=" + width; Runtime runtime = Runtime.getRuntime(); Process process = null; StringBuilder logBuilder = new StringBuilder(); StringBuilder errorBuilder = new StringBuilder(); int status = 0; try { //作業ディレクトリをjave5ディレクトリに移して処理する process = runtime.exec(commandArray, null, new File(javeDir)); final InputStream in = process.getInputStream(); final InputStream ein = process.getErrorStream(); Runnable inputStreamThread = () -> { BufferedReader reader = null; String line; try { reader = new BufferedReader(new InputStreamReader(in)); while (true) { line = reader.readLine(); if (line == null) { break; } logBuilder.append(line).append("\n"); } } catch (Exception e) { } finally { if (reader != null) { try { reader.close(); } catch (Exception e) { } } } }; Runnable errorStreamThread = () -> { BufferedReader reader = null; String line; try { reader = new BufferedReader(new InputStreamReader(ein)); while (true) { line = reader.readLine(); if (line == null) { break; } errorBuilder.append(line).append("\n"); } } catch (Exception e) { } finally { if (reader != null) { try { reader.close(); } catch (Exception e) { } } } }; Thread inThread = new Thread(inputStreamThread); Thread errorThread = new Thread(errorStreamThread); inThread.start(); errorThread.start(); status = process.waitFor(); inThread.join(); errorThread.join(); } finally { if (process != null) { try { process.destroy(); } catch (Exception e) { } } } System.out.format("変換結果\n%1$s", logBuilder.toString()); //ここから追加分 //AA→画像ファイルの保存場所 String outputFilePath = "ascii.png"; //標準の等幅フォントを使う String fontName = Font.MONOSPACED; GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); Font[] fonts = ge.getAllFonts(); for (Font font : fonts) { //MSゴシックがある環境であれば優先して使う if ("MS Gothic".equals(font.getName())) { fontName = font.getFontName(); break; } } Font font = new Font(fontName, Font.PLAIN, 12); //Graphics・FontMetricsを取得するためのダミー BufferedImage image = new BufferedImage(1, 1, BufferedImage.TYPE_USHORT_GRAY); Graphics2D graphics = image.createGraphics(); FontMetrics metrics = graphics.getFontMetrics(font); //文字間のピクセル(調整値) int colMargin = 0; //行間のピクセル(調整値) int rowMargin = 0; //等幅フォントの幅を取得する int fontWidth = metrics.charWidth(' '); //等幅フォントの高さを取得する(FontMetrics#getHeightは行間のサイズまで入ってしまうので使わない) int fontHeight = metrics.getDescent() + metrics.getAscent(); String[] lines = logBuilder.toString().split("\n"); //フォントの幅・高さから計算されるImageを生成する image = new BufferedImage(fontWidth * width + (width - 1) * colMargin, fontHeight * lines.length + (lines.length - 1) * rowMargin, BufferedImage.TYPE_USHORT_GRAY); graphics = image.createGraphics(); //背景を白に graphics.setColor(Color.WHITE); graphics.fillRect(0, 0, image.getWidth(), image.getHeight()); //文字を黒に graphics.setColor(Color.BLACK); //フォントも忘れず指定 graphics.setFont(font); //文字間の調整がある場合は1文字ずつ位置を決めながら描画する if (colMargin > 0) { for (int i = 0; i < lines.length; i++) { for (int j = 0; j < lines[i].length(); j++) { //描画したい行の一番上から描画するのではなく、FontMetrics#getAscentで得られたベースラインを基準に描画する graphics.drawString(String.valueOf(lines[i].charAt(j)), (fontWidth + colMargin) * j, (fontHeight + rowMargin) * i + metrics.getAscent()); } } } //文字間の調整がない場合はまとめて描画する else { for (int i = 0; i < lines.length; i++) { //描画したい行の一番上から描画するのではなく、FontMetrics#getAscentで得られたベースラインを基準に描画する graphics.drawString(lines[i], 0, (fontHeight + rowMargin) * i + metrics.getAscent()); } } ImageIO.write(image, "png", new File(outputFilePath)); } }
動作確認
$ javac ImageToAscii.java $ java ImageToAscii (AAが出力されるため省略)
変換前の画像は以下のファイルです。
今回はWindowsとCentOSで実行し、フォントの違いによる差を確認しました。
環境
開発
動作検証
上記の実装をベースにWebツールも公開しています。 AA変換(アスキーアート生成)|Web便利ツール@ツールタロウ
Java 画像→AA
はじめに
画像をアスキーアートに変換します。 事前に以下のアプリケーションを用意します。
- JavE
- http://www.jave.de/download/download.html
- ※"jave5.zip"のリンクからダウンロード
ライブラリとして使う方法が見当たらなかったため、Runtime経由でjavaコマンドで起動します。 変換前の画像は変換後の状態と並べて後述します。
実装例
サンプルでは、動作確認しやすいようにmainメソッドで実行できるようにしてあります。 結果だけを確認したい場合は、この記事の一番下のリンク先で使えるようにしてありますのでご覧ください。
import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; /** * * @author tool-taro.com */ public class ImageToAscii { public static void main(String[] args) throws IOException, InterruptedException { //Javaのパス String javaPath = "/usr/java/latest/bin/java"; //jave5のディレクトリ String javeDir = "/usr/local/jave5"; //jave5.jarのパス String javePath = "/usr/local/jave5/jave5.jar"; //読み取りたい画像ファイルの保存場所 String inputFilePath = "input.jpg"; //Ascii文字数(横) int width = 200; String[] commandArray = new String[6]; int index = 0; commandArray[index++] = javaPath; commandArray[index++] = "-jar"; commandArray[index++] = javePath; commandArray[index++] = "image2ascii"; commandArray[index++] = inputFilePath; commandArray[index++] = "width=" + width; Runtime runtime = Runtime.getRuntime(); Process process = null; StringBuilder logBuilder = new StringBuilder(); StringBuilder errorBuilder = new StringBuilder(); int status = 0; try { //作業ディレクトリをjave5ディレクトリに移して処理する process = runtime.exec(commandArray, null, new File(javeDir)); final InputStream in = process.getInputStream(); final InputStream ein = process.getErrorStream(); Runnable inputStreamThread = () -> { BufferedReader reader = null; String line; try { reader = new BufferedReader(new InputStreamReader(in)); while (true) { line = reader.readLine(); if (line == null) { break; } logBuilder.append(line).append("\n"); } } catch (Exception e) { } finally { if (reader != null) { try { reader.close(); } catch (Exception e) { } } } }; Runnable errorStreamThread = () -> { BufferedReader reader = null; String line; try { reader = new BufferedReader(new InputStreamReader(ein)); while (true) { line = reader.readLine(); if (line == null) { break; } errorBuilder.append(line).append("\n"); } } catch (Exception e) { } finally { if (reader != null) { try { reader.close(); } catch (Exception e) { } } } }; Thread inThread = new Thread(inputStreamThread); Thread errorThread = new Thread(errorStreamThread); inThread.start(); errorThread.start(); status = process.waitFor(); inThread.join(); errorThread.join(); } finally { if (process != null) { try { process.destroy(); } catch (Exception e) { } } } System.out.format("変換結果\n%1$s", logBuilder.toString()); } }
動作確認
$ javac ImageToAscii.java $ java ImageToAscii (AAが出力されるため省略)
変換前の画像は以下のファイルです。
変換後の文字列はテキストエディタに貼りつけてキャプチャしました。
環境
上記の実装をベースにWebツールも公開しています。 AA変換(アスキーアート生成)|Web便利ツール@ツールタロウ