ConoHaのVPS

さくらのVPSを1台借りていて2つのドメインで使用しているのだが、

やっぱり物理的に(VPSだから本当は物理的にではないが)2台ほしくなってきた。

さくらのVPSには何の不満もないのだが、VPSってほかにもないのかなと調べてみたら、
なんとConoHaというサービスの利用者はさくらより多いということを知った。

てっきりVPSといえばさくらだと思っていたのだが。

サービス内容をざっと見したところさくらとそんなに違うところはない。

初期費用がない、特定の用途向けのパッケージみたいなものがある、
というのが気づいたところ。

OSはCentOS8にした。去年リリースされたそうだ。

ようやくCentOS7に慣れたところだが、きっとこれから使うことになると思うので
勉強を兼ねて。

6→7 ほどの違いはないっぽい。

yumがdnfというものになっているそうだが、yumも使える。

yumはpython2ベース、dnfはpython3ベース。

python2と3のゴタゴタは嫌だったのでこっちの方がいい。



TCPまたはUDPパケットを送信する。javaで。

UDPかTCPを指定できるようにした。 Clientx.java
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.io.DataOutputStream;
import java.net.Socket;


public class Clientx {
 public static void main(String[] args) throws IOException{
  String sendData = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef";

  String Host = args[0];
  Integer DstPort = Integer.parseInt(args[1]);
  int count = Integer.parseInt(args[2]);
  String Proto = args[3];
 
  System.out.println(Proto);

  if (Proto.equals("U")) {
   UDPsend(sendData,Host,DstPort,count);
  }else{
   TCPsend(sendData,Host,DstPort,count);
  }
 }

 public static void UDPsend(String sdata, String host, int dstPort, int count) throws IOException{
  byte[] bdata = sdata.getBytes("UTF-8");
  DatagramSocket sock = new DatagramSocket();
  DatagramPacket packet 
  = new DatagramPacket(bdata, bdata.length, new InetSocketAddress(host,dstPort));


  for(int i=1; i<=count; i++) {  
   sock.send(packet);
   System.out.println("Sent UDP data  "+host+":"+dstPort);
    try{
    Thread.sleep(1000);
   }catch(InterruptedException e){}
  }
  sock.close();//
 }

 public static void TCPsend(String sdata, String host, int dstPort, int count) {
  try{

   for(int i=1; i<=count; i++) {  
    Socket sock = new Socket(host,dstPort);
    DataOutputStream out = new DataOutputStream(sock.getOutputStream());
    out.writeUTF(sdata);
    System.out.println("Sent TCP data  "+host+":"+dstPort);

    out.close();
    sock.close();
     try{
     Thread.sleep(1000);
    }catch(InterruptedException e){}
   }

  }catch(IOException e){
   e.printStackTrace();
  }

 }
}
------------- 

 使い方 

 TCP12345のパケットを5個送信 

java Clientx localhost 12345 5 T 

 UDP12345のパケットを5個送信 

java Clientx localhost 12345 5 U 

 実際は4番目の引数が"U"ならUDP、それ以外だとTCPになる。 

4番目の引数がないと動かない。 

UDPの場合はport unreachableが返ってきてもとりあえず送信はするが、 
TCPの場合受信者がいないと(指定したTCPポートをリッスンしていない)と、 
1回送ってExceptionを吐いて終了してしまう。 

 TCPのサーバも作った。 TCPのサーバ 

 ServerT.java
import java.io.IOException;
import java.io.DataInputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class ServerT {
 public static void main(String[] args) {
  try{
   while(true){
    ServerSocket svSock = new ServerSocket(12345);
    Socket sock = svSock.accept();
    DataInputStream in = new DataInputStream(sock.getInputStream());
    String strData = in.readUTF();
    System.out.println("Received TCP : "+strData);
    in.close();
    svSock.close();
   }
  }catch(IOException e){
   e.printStackTrace();
  }

 }
}
UDP/TCPどっちでも受信できるようにするのはまた今度。

任意のパケットを送信する。javaで。UDP編

たとえばFirewallのポリシーの設定確認のときに、任意のパケットを送信したいことがある。 UDP 1234とか、TCP 5678とか。

ICMPならpingを打てばよいし、HTTP、HTTPS、SSH、TELNETなどならブラウザやteratermで実際にアクセスしてみればいい。TCPならtelnetでポート指定すればよいが、UDPの特定のポートの通信を発生させるためにはツールを使っていた。ipsendwinとか、iperfとか。 ixiaのトラフィックジェネレータを使ったこともある。

最近もipsendwinを使ったのだが、もう古いソフトで、Vectorのダウンロード画面ではサポートOSに「Windows XP/Me/2000/NT/98/95」と書いてある。 そしてあるPCでは「winpcap.dllがない」と表示され、コピーするもまた違うdllがない、エントリポイントが見つからない、などどいうことで実行するのをあきらめた。

そして、このご時世、いろんなアプリやスクリプトがあるし、「UDP 1234のパケットを特定のIPアドレスに10個ほど送信する」なんてことは簡単にできるんじゃないのかと思った。

pythonとかjavascriptとかさらっと調べたが、結局javaでやった。

java。 ちょっと、今更java?みたいな感じがした。 javaで簡単なプログラムを書いたことはあり、 簡単に書けて「ネットワークプログラミングならjavaだな」と思った。

しかし、javaは当然インストールされているだろうと思って普段仕事でつかっているPCのコントロールパネルを見たがjavaがインストールされていない。 たしかコントロールパネルにjavaのアイコンがあったはず.... もう最近はjavaが使われなくなりつつあるのか?

というわけでjavaのインストールから始める。 「java ダウンロード」などで検索するとダウンロードページがすぐ出てくるが、 32ビット版をインストールするように導かれる。 今なら、Version 8 Update 241 64ビット版もあるようだがどういうことだろうと少し調べたら、 ブラウザが32ビット版がデフォルトなのでjavaも32ビット版を使え、ということだった。

https://java.com/ja/download/faq/java_win64bit.xml

普段はクロームを使っているが64ビット版である。 が、たしかクロームでjavaが使えなくなったんじゃなかったっけ...?

IEはたしかに32ビット版のようである。使っていないが。 javaのランタイムは32ビット版のインストールページが検索すると上位に表示されるが、 開発環境、jdkだと13.0.2の64ビット版が出てくる。

32ビット版のランタイムがインストールされているところに64ビット版のjdkをインストールすると、実行時にエラーになる。 ランタイムは入れず、入っていたらアンインストールし、64ビット版のjdkをインストールする。 インストールしたら、binフォルダへのpathを登録する。

C:\Program Files\Java\jdk-13.0.2\bin

pathを登録したらコマンドプロンプトを開いてバージョンを確認してみる。

C:\WINDOWS\system32>javac -version
javac 13.0.2

HelloWorld.java を作る。

public class HelloWorld{
   public static void main(String[] args){
     System.out.println("Hello World!!");
   }
}
javac HelloWorld.java

でコンパイル。 HelloWorld.class ができる。

 実行。

C:\WINDOWS\system32>java HelloWorld
Hello World!!

では、UDPの任意のパケットを送信するプログラムを書こう。

 Client.java

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
public class Client {
 public static void main(String[] args) throws IOException {
  String sendData = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef";
  byte[] data = sendData.getBytes("UTF-8");
  DatagramSocket sock = new DatagramSocket();
   int count = Integer.parseInt(args[2]);
  String Host = args[0];
  Integer DestPort = Integer.parseInt(args[1]);
   for(int i=1; i<=count; i++) {  
   DatagramPacket packet 
   = new DatagramPacket(data, data.length, new InetSocketAddress(Host,DestPort));
   sock.send(packet);
   System.out.println("Sent UDP data  "+Host+":"+DestPort);
    try{
    Thread.sleep(1000);
   }catch(InterruptedException e){}
   }  
   sock.close();//
 }
}

使い方
java Client 宛先 ポート番号 パケット数

たとえば

java Client 192.168.1.1 12345 5

192.168.1.1宛に、UDP の宛先ポート12345のパケットを5個送信する。
間隔は1秒

送るだけならこれで終わり。 もし指定したIPアドレスのホストが存在しないと、arp解決されずパケットが送信されないだろう。 指定したIPアドレスのホストが存在すればパケットが送信されるが、 テキトーなポート宛に送っているので、port unreachableが返ってくるだろう。 送ったパケットを受信しそれを確認したい場合は受信側で下記を実行する。

Server.java

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.util.Arrays;
public class Server {
        public static void main(String[] args) throws IOException {
                Integer Port = Integer.parseInt(args[0]);
                while (true) {
                        DatagramSocket sock = new DatagramSocket(Port);
                        byte[] data = new byte[1024];
                        DatagramPacket packet = new DatagramPacket(data, data.length);
                        sock.receive(packet);
                        System.out.println("Received :"+new String(Arrays.copyOf(packet.getData(),packet.getLength()),"UTF-8"));
                        sock.close();
                }
        }
}

動作確認 Client.javaとServer.javaをコンパイルしたら、 コマンドプロンプトを二つ起動して、 Client.classとServer.classがあるフォルダに移動し、片側でサーバを起動するこのときポート番号を指定する。

C:\Users\sam\udp_data_send>java Server 12345

もう一方でクライアントを起動する。
C:\Users\sam\udp_data_send>java Client localhost 12345 10
Sent UDP data  localhost:12345
Sent UDP data  localhost:12345
Sent UDP data  localhost:12345
Sent UDP data  localhost:12345
Sent UDP data  localhost:12345
Sent UDP data  localhost:12345
Sent UDP data  localhost:12345
Sent UDP data  localhost:12345
Sent UDP data  localhost:12345
Sent UDP data  localhost:12345
C:\Users\sam\udp_data_send>java Server 12345
Received :0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
Received :0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
Received :0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
Received :0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
Received :0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
Received :0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
Received :0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
Received :0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
Received :0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
Received :0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
TCPはまた今度。